<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2022/9/1
 * Time: 上午11:42
 */

namespace app\common\lib\astrolog;

use app\astro\controller\Housescore;
use app\astro\controller\Planetpower;
use app\common\model\AspectChange;
use app\common\model\AstroChange;
use think\Db;
use think\db\Query;

/**
 * Class DailyFortune
 * @package app\common\lib\astrolog
 */
class DailyFortune extends LogicBase
{
    /**
     * 单例
     * @var DailyFortune
     */
    protected static $instance;

    protected $advance = [];

    /**
     * 行运盘数据
     * @var array
     */
    protected $transitsData = [];

    /**
     * 比较盘数据
     * @var array
     */
    protected $synastryData = [];

    /**
     * 主档案信息
     * @var array
     */
    protected $mainRecord = [];

    /**
     * 其他档案信息
     * @var array
     */
    protected $otherRecordList = [];

    /**
     * 星盘配置
     * 行运盘使用原来日运里面的星盘配置
     * 合盘使用 合盘功能中的星盘配置
     * @var array
     */
    protected $setting = [
        'now' => [
            'planet' => [
                [1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1, 0],
                [0, 0], [0, 0], [1, 0], [0, 0], [0, 0], [0, 0], [0, 0], [1, 0], [0, 0], [0, 0], [1, 0]
            ],
            'phase' => [
                0 => [1, 2], 60 => [1, 1], 90 => [1, 2], 120 => [1, 2], 180 => [1, 2],
                45 => [0, 0], 135 => [0, 0], 30 => [0, 0], 150 => [0, 0], 72 => [0, 0], 144 => [0, 0]
            ],
            'arabic' => [
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
            ],
            'h_sys' => 'p',
            'firdaria' => 'default',
            'bound_type' => 'default',
            'ecliptic' => 0,
            'profection_push_direction' => 0,
            'decanates' => 0,
            'ayanamsa' => 0,
            'location_use' => 0
        ],
        'natal' => [
            'planet' => [
                [1, 7.5], [1, 6], [1, 3.5], [1, 4], [1, 4], [1, 4.5], [1, 4.5], [1, 2.5], [1, 2.5], [1, 2.5],
                [0, 0], [0, 0], [1, 0], [0, 0], [1, 2.5], [0, 0], [1, 0], [1, 2.5], [1, 2.5], [1, 2.5], [1, 2.5]
            ],
            'phase' => [
                0 => [1, 0], 60 => [1, 0], 90 => [1, 0], 120 => [1, 0], 180 => [1, 0],
                45 => [0, 0], 135 => [0, 0], 30 => [0, 0], 150 => [0, 0], 72 => [0, 0], 144 => [0, 0]
            ],
            'arabic' => [
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
            ],
            'h_sys' => 'p',
            'firdaria' => 'default',
            'bound_type' => 'default',
            'ecliptic' => 0,
            'profection_push_direction' => 0,
            'decanates' => 0,
            'ayanamsa' => 0,
            'location_use' => 0
        ],
        'transits' => [
            'asp_orb_all' => [0 => 3, 60 => 2, 90 => 3, 120 => 3, 180 => 3, 30 => 1, 150 => 2, 45 => 2, 135 => 2, 72 => 2, 144 => 2],
            'asps_display' => [0, 60, 90, 120, 180],
            'planets_display' => '111111111100000001001',
            'planet_orb_all' => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            'h_sys' => 'p',
        ],
        'synastry' => [
            'asp_orb_all' => [0 => 3, 60 => 2, 90 => 3, 120 => 3, 180 => 3, 30 => 1, 150 => 2, 45 => 2, 135 => 2, 72 => 2, 144 => 2],
            'asps_display' => [0, 60, 90, 120, 180],
            'planets_display' => '111111111100100001001',
            'planet_orb_all' => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            'h_sys' => 'p',
        ],
        'thirdprogressed' => [
            'asp_orb_all' => [0 => 6, 60 => 4, 90 => 5, 120 => 5, 180 => 5, 30 => 1, 150 => 2, 45 => 2, 135 => 2, 72 => 2, 144 => 2],
            'asps_display' => [0, 60, 90, 120, 180],
            'planets_display' => '111111111100000001001',
            'planet_orb_all' => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            'h_sys' => 'p',
        ],
    ];

    /**
     * 变动类型
     *  0=>首页,1=>星象变动,2=>纯净,3=>进行
     * @var bool
     */
    protected $changeType = false;

    /**
     * 进行中计算限制几条
     * @var int
     */
    protected $doingLimit = 0;

    /**
     * 构造方法
     * 单例模式，私有化
     * 只能通过 getInstance 公共方法获取实例
     * DailyFortune constructor.
     */
    private function __construct()
    {
    }

    /**
     * 获取实例
     * @return DailyFortune
     */
    public static function getInstance(): DailyFortune
    {
        if (!(self::$instance instanceof self))
        {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 设置主档案信息
     * @param array $record
     * @return $this
     */
    public function setMainRecord($record = [])
    {
        if (!empty($record))
        {
            $this->mainRecord = $record;

            if (!isset($this->advance['longitude']))
            {
                $this->advance['longitude'] = ($record['long_deg'] + $record['long_min'] / 60) * $record['ew'];
            }
            if (!isset($this->advance['latitude']))
            {
                $this->advance['latitude'] = ($record['lat_deg'] + $record['lat_min'] / 60) * $record['ns'];
            }
        }
        return $this;
    }

    /**
     * 设置参与的档案列表
     * @param array $recordList
     * @return $this
     */
    public function setOtherRecordList($recordList = [])
    {
        if (!empty($recordList))
        {
            $this->otherRecordList = $recordList;
        }
        return $this;
    }

    /**
     * 设置运势时间
     * @param string/int $advance 2022-09-29/2022-09-29 14:16:28/1664432188
     * @return $this
     */
    public function setAdvance($advance = '')
    {
        // 2022-09-05
        if (is_string($advance))
        {
            if (strlen($advance) === 10)
            {
                $advance .= ' 12:00:00';
            }
            $time = strtotime($advance);
        } else
        {
            $time = $advance;
        }
        // 推进时间
        $timeinfo = [
            'year' => (int)(date('Y', $time)),
            'month' => (int)(date('m', $time)),
            'day' => (int)(date('d', $time)),
            'hour' => (int)(date('H', $time)),
            'minute' => (int)(date('i', $time)),
            'timezone' => 8, // 默认北京时间
            'is_summer' => 0,
        ];
        $this->advance = $timeinfo;
        return $this;
    }

    /**
     * 设置是否计算进行中
     * @param $value
     * @return $this
     */
    public function setChangeType($value)
    {
        $this->changeType = (int)$value;
        return $this;
    }

    /**
     * 设置进行中只计算多少条 0表示不限制
     * @param int $limit
     * @return $this
     */
    public function setDoingLimit($limit = 0)
    {
        $this->doingLimit = (int)$limit;
        return $this;
    }

    /**
     * 谁是你今天的的幸运伙伴
     */
    public function luckyPartner()
    {
        $data = $hard = [];
        /**
         * 获取星盘数据（行运盘+比较盘）
         */
        $this->transitsData = [];
        $this->synastryData = [];
        $execPrefix = config('astrolog.prefix');
        $astro = Astrolog::getInstance()
            ->setRecode1($this->mainRecord)
            ->setAdvance($this->advance)
            ->setExecPrefix($execPrefix)
            ->setIsAstrolabe(true)
            ->setUserSetting($this->setting)
            ->setVersion(2)
            ->setGetDatas(['transits'])
            ->getAstroDatas();
        $this->transitsData = json_decode(json_encode($astro->getDatas('transits')), true);
        /**
         * 找出你在流年受困的星体
         */
        $hard = [
            'rid' => $this->mainRecord['id'],
            'name' => $this->mainRecord['name'],
            'data' => $this->getPlanetForSuffering($this->transitsData),
        ];

        foreach ($this->otherRecordList as $record)
        {
            $astro = $astro
                ->setRecode1($this->mainRecord)
                ->setRecode2($record)
                ->setGetDatas(['synastry'])
                ->getAstroDatas();
            $this->synastryData = json_decode(json_encode($astro->getDatas('synastry')), true);
            $astro = $astro
                ->setRecode1($record)
                ->setGetDatas(['transits'])
                ->getAstroDatas();
            $transitsData = json_decode(json_encode($astro->getDatas('transits')), true);
            /**
             * 找出善待你受困星体的合盘
             */
            $score = $this->getSaviorForYou($hard, $this->synastryData, $transitsData);

            $data[] = [
                'rid' => $record['id'],
                'name' => $record['name'],
                'score' => $score
            ];
        }
        // 按最终分数进行排序，倒序
        $data = resort($data, 'score', 'DESC');

        return $data;
    }

    /**
     * 找出你在流年受困的星体
     * @param array $transits
     * @param bool $isOther
     * @return array
     */
    protected function getPlanetForSuffering($transits = [], $isOther = false): array
    {
        //	找出你在流年受困的星体
        //		目标星体 日月金水火木，命主 （底盘）
        //			各星重要系数：月1.2，日1，金0.9，水0.7，火0.7，木0.4，命主0.5（某星同为命主可叠加） （外盘星体）
        //		计算各目标星体受困指数
        //			各星困难指数：天海冥10，土30，火60，日月水30 （外盘星体）
        //			相位系数：合1（无日月水），刑冲1.2，拱六分0.7（无日月水）（外盘星体）
        //			容许系数： <0.5=1;<1=0.95;<1.5=0.85; 0.7
        //			多星作用：当目标星体与两个甚至以上星体成相位，则额外增加10*A，A为目标星体成刑冲相或与凶星（仅看火土冥）成相的相位个数
        //      结果=困难指数*容许系数*相位系数+多星作用额外分
        $data = [];
        /**
         * 目标星体 日月金水火木，命主 （底盘）
         * id  星体ID 日月金水火木，命主 （外盘星体）
         * x 各星重要系数 月1.2，日1，金0.9，水0.7，火0.7，木0.4，命主0.5（某星同为命主可叠加）
         */
        $mainPlanetList = [
            ['id' => 0, 'x' => 1, 'score' => 0],
            ['id' => 1, 'x' => 1.2, 'score' => 0],
            ['id' => 2, 'x' => 0.7, 'score' => 0],
            ['id' => 3, 'x' => 0.9, 'score' => 0],
            ['id' => 4, 'x' => 0.7, 'score' => 0],
            ['id' => 5, 'x' => 0.4, 'score' => 0],
            ['id' => $transits[0]['houses'][1]['protect_ancient_id'], 'x' => 0.5, 'score' => 0],
        ];
        // 是否没有受困星体
        $isEmpty = true;
        // 各星困难指数：天海冥10，土30，火60，日月水30（外盘星体）
        $hardList = [0 => 30, 1 => 30, 2 => 30, 4 => 60, 6 => 30, 7 => 10, 8 => 10, 9 => 10];
        // 相位系数：合1（无日月水），刑冲1.2，拱六分0.7（无日月水）
        $phaseList = [0 => 1, 60 => 0, 90 => 0, 120 => 0, 180 => 0];
        // 容许系数：<0.5=1;<1=0.95;<1.5=0.85; 0.7
        foreach ($mainPlanetList as $k => $main)
        {
            if ($isOther && !in_array($main['id'], [0, 1, 3], true))
            {
                continue;
            }
            $planet = $transits[0]['planets'][$main['id']];
            if (!empty($planet['phase']))
            {
                $more = 0;
                foreach ($planet['phase'] as $phase)
                {
                    // 仅看日月水火土天海冥
                    if (array_key_exists($phase['id'], $hardList))
                    {
                        // 计算容许系数
                        if ($phase['phase_orb'] < 0.5)
                        {
                            $po = 1;
                        } elseif ($phase['phase_orb'] < 1)
                        {
                            $po = 0.95;
                        } elseif ($phase['phase_orb'] < 1.5)
                        {
                            $po = 0.85;
                        } else
                        {
                            $po = 0.7;
                        }
                        /**
                         * 合相（不看日月水）
                         * 邢冲
                         * 拱六分（不看日月水）
                         */
                        if (($phase['phase_e'] === 0 && !in_array($phase['id'], [0, 1, 2], true))
                            || in_array($phase['phase_e'], [90, 180], true)
                            || in_array($phase['phase_e'], [60, 120], true))
                        {
                            // 结果=困难指数*容许系数*相位系数+多星作用额外分
                            $mainPlanetList[$k]['score'] += $hardList[$phase['id']] * $po * $phaseList[$phase['phase_e']];
                        }
                        // 多星作用：当目标星体与两个甚至以上星体成相位，则额外增加10*A，A为目标星体成刑冲相或与凶星（仅看火土冥）成相的相位个数
                        if (in_array($phase['phase_e'], [90, 180], true) || in_array($phase['id'], [4, 6, 9], true))
                        {
                            $more++;
                        }
                    }
                }
                $mainPlanetList[$k]['score'] += 10 * $more;
            }
            $data[$k] = $mainPlanetList[$k];
            if ($mainPlanetList[$k]['score'] > 0) $isEmpty = false;
        }
//        if ($isEmpty)
//        {
//            $data[0]['score'] = 1;
//            $data[1]['score'] = 1;
//            $data[3]['score'] = 1;
//        }
        return $data;
    }

    /**
     * 找出你今天的贵人
     * @param array $hard 受困星体数据
     * @param array $synastry 比较盘数据
     * @param array $transits 目标盘行运数据
     * @return number
     */
    protected function getSaviorForYou($hard = [], $synastry = [], $transits = [])
    {
        $s1 = array_sum(array_column($hard['data'], 'score'));
        // 如无受困星，用户盘取日月金，受困指数取目标盘日月金的受困指数
        if ($s1 <= 0)
        {
            $hard['data'] = $this->getPlanetForSuffering($transits, true);
            $s2 = array_sum(array_column($hard['data'], 'score'));
            if ($s2 <= 0)
            {
                $hard['data'][0]['score'] = 1;
                $hard['data'][1]['score'] = 1;
                $hard['data'][3]['score'] = 1;
            }
        }

        $score = 0;
        //	找出善待你受困星体的合盘
        //		计算善待值
        //			目标星体 日月金水火木，命主
        //			善待指数
        //				各星体成相
        //					金/木 合70、拱六分60、冲40、刑25
        //					日/月 合55、拱六分45，冲20
        //					水 合35、拱六分20
        //					火/土 拱六分 10
        //			虐待指数
        //				各星体成相
        //					火/土 合20、刑冲40
        //					日/月 刑25
        //					水 刑冲20
        //			善待值=善待指数-虐待指数
        //		用户盘当下各星的受困指数（仅不为零的星），与目标盘对应星体的善待值进行对比，每颗星的救应指数=（善待值-受困指数）*该星重要系数，最后求和
        //	按解救程度排名
        //		对列表或者选定的档案群进行检测，得出排行
        foreach ($hard['data'] as $k => $h)
        {
            if ($h['score'] > 0 && !empty($synastry[0]['planets'][$h['id']]['phase']))
            {
                $st = 0;
                foreach ($synastry[0]['planets'][$h['id']]['phase'] as $phase)
                {
                    switch ($phase['id'])
                    {
                        case 0:
                        case 1:
                            // 善待值：日/月 合55、拱六分45，冲20
                            if ($phase['phase_e'] === 0)
                            {
                                $st += 55;
                            } elseif (in_array($phase['phase_e'], [60, 120], true))
                            {
                                $st += 45;
                            } elseif ($phase['phase_e'] === 180)
                            {
                                $st += 20;
                            } // 虐待值：日/月 刑25
                            elseif ($phase['phase_e'] === 90)
                            {
                                $st -= 25;
                            }
                            break;
                        case 2:
                            // 善待值：水 合35、拱六分20
                            if ($phase['phase_e'] === 0)
                            {
                                $st += 35;
                            } elseif (in_array($phase['phase_e'], [60, 120], true))
                            {
                                $st += 20;
                            } // 虐待值：水 刑冲20
                            elseif (in_array($phase['phase_e'], [90, 180], true))
                            {
                                $st -= 20;
                            }
                            break;
                        case 3:
                        case 5:
                            // 善待值：金/木 合70、拱六分60、冲40、刑25
                            if ($phase['phase_e'] === 0)
                            {
                                $st += 70;
                            } elseif (in_array($phase['phase_e'], [60, 120], true))
                            {
                                $st += 60;
                            } elseif ($phase['phase_e'] === 180)
                            {
                                $st += 40;
                            } elseif ($phase['phase_e'] === 90)
                            {
                                $st += 25;
                            }
                            break;
                        case 4:
                        case 6:
                            // 善待值：火/土 拱六分 10
                            if (in_array($phase['phase_e'], [60, 120], true))
                            {
                                $st += 10;
                            } // 虐待值：火/土 合20、刑冲40
                            elseif ($phase['phase_e'] === 0)
                            {
                                $st -= 20;
                            } elseif (in_array($phase['phase_e'], [90, 180], true))
                            {
                                $st -= 40;
                            }
                            break;
                    }
                }
                $score += ($st - $h['score']) * $h['x'];
            }
        }
        return $score;
    }

    /**
     * 感受度计算（一天）
     */
    public function sensitivity()
    {
        $res = [];
        if (in_array($this->changeType, [1, 2], true))
        {
            /**
             * 计算天象 换座、逆行、相位、日月食
             */
            $res = $this->getDataFromNow();
            $trList = [];
            $tpList = [];
            if (!empty($this->mainRecord))
            {
                /**
                 * 计算行运 入宫、相位
                 */
                $trList = $this->getDataFromTransits();
                /**
                 * 计算三限 入宫、相位
                 */
                $tpList = $this->getDataFromProgression();
            }

            $res = resort(array_merge($res, $trList, $tpList), 'time', 'ASC');

            // 星象变动：功能推荐
            if ($this->changeType === 1 && !empty($this->mainRecord))
            {
                $this->recommendUnlock($res);
            }
        } elseif ($this->changeType === 3)
        {
            /**
             * 查询进行中的天象：逆行、日月食、相位
             *    逆行：   水星在白羊座逆行
             *    日月食： 金牛座日食
             *    相位：   月亮冲火星
             * 查询进行中的行运：相位
             *    相位：   月亮冲火星
             * 查询进行中的三限：相位
             *    相位：   月亮冲火星
             */
            // 开始获取当前天象数据，检测已有相位、逆行、
            $nowTime = time();
            $zeroNowTime = strtotime('-8hour', $nowTime);
            $zeroNowStartTime = strtotime('-8hour', strtotime(date('Y-m-d' . ' 00:00:00', $nowTime)));
            $timeinfo = [
                'year' => (int)(date('Y', $nowTime)),
                'month' => (int)(date('m', $nowTime)),
                'day' => (int)(date('d', $nowTime)),
                'hour' => (int)(date('H', $nowTime)),
                'minute' => (int)(date('i', $nowTime)),
                'timezone' => 8,
                'is_summer' => 0,
            ];
            $execPrefix = config('astrolog.prefix');
            $astro = Astrolog::getInstance()
                ->setAdvance($timeinfo)
                ->setExecPrefix($execPrefix)
                ->setIsAstrolabe(true)
                ->setUserSetting($this->setting)
                ->setVersion(2);
            if (!empty($this->mainRecord))
            {
                $astro = $astro->setRecode1($this->mainRecord)->setGetDatas(['now', 'transits', 'thirdprogressed'])->getAstroDatas();
                $transitsData = json_decode(json_encode($astro->getDatas('transits')), true);
                $thirdprogressedData = json_decode(json_encode($astro->getDatas('thirdprogressed')), true);
            } else
            {
                $astro = $astro->setGetDatas(['now'])->getAstroDatas();
            }
            // 获取当前时间天象、行运、三限的星盘
            $nowData = json_decode(json_encode($astro->getDatas('now')), true);

            $nw_st_time = microtime(true);
            // 天象数据
            for ($i = 0; $i < 10; $i++)
            {
                if ($this->doingLimit > 0 && count($res) >= $this->doingLimit)
                {
                    return $res;
                }
                // 逆行数据
                if ($i > 1 && $nowData['planets'][$i]['speed'] < 0)
                {
                    // 推算逆行开始的时间，数据库查询
                    $startTime = (new AstroChange())->where(['type' => 2, 'pid' => $i, 'speed' => 2])
                        ->whereTime('time', '<', date('Y-m-d H:i:s', $zeroNowTime))
                        ->order('time desc')->limit(1)->value('time');
                    $endTime = (new AstroChange())->where(['type' => 2, 'pid' => $i, 'speed' => 1])
                        ->whereTime('time', '>', date('Y-m-d H:i:s', $zeroNowTime))
                        ->order('time asc')->limit(1)->value('time');
                    $s = $this->getRetroScore(['pid' => $i], strtotime($startTime), strtotime($endTime));
                    $startTimeBj = strtotime('+8 hour', strtotime($startTime));
                    $endTimeBj = strtotime('+8 hour', strtotime($endTime));
                    $textStatus = $this->transerData(['type' => 2, 'pid' => $i]);
                    $res[] = [
                        'type' => 2,
                        'tag' => '天象',
                        'title' => $textStatus['text'],
                        'pid' => $i,
                        'pid1' => null,
                        'pid2' => null,
                        'phase' => null,
                        'in_sign_id' => null,
                        'in_house_id' => null,
                        'state' => 0,
                        'score' => $s,
                        'time' => $nowTime,
                        'start_time' => $startTimeBj,
                        'end_time' => $endTimeBj,
                        'status' => $textStatus['status'],
                        'code' => sprintf("%01d%01d%02d%03d%02d", 1, 4, $i, 0, 2),
                        'time_text' => date('Y-m-d H:i:s', $startTimeBj) . ' 到 ' . date('Y-m-d H:i:s', $endTimeBj),
                    ];
                }
                // 相位
                if (!empty($nowData['planets'][$i]['phase']))
                {
                    foreach ($nowData['planets'][$i]['phase'] as $phase)
                    {
                        // 仅检测成相星体ID比当前星体ID数值要大的相位，避免相位重复检测(1-4||4-1) 天象不检测轴点相位
                        //  && !in_array($phase['id'], [ASC, MC], true)
                        if ($phase['id'] > $i && $phase['id'] < 10)
                        {
                            // 开始获取成相时间
                            $startTime = (new AspectChange())->where(['pid1' => $i, 'pid2' => $phase['id'], 'phase' => $phase['phase_e'], 'state' => 1])
                                ->whereTime('time', '<', date('Y-m-d H:i:s', $zeroNowTime))
                                ->order('time desc')->limit(1)->value('time');
                            // 开始获取结束成相时间
                            $endTime = (new AspectChange())->where(['pid1' => $i, 'pid2' => $phase['id'], 'phase' => $phase['phase_e'], 'state' => 3])
                                ->whereTime('time', '>', date('Y-m-d H:i:s', $zeroNowTime))
                                ->order('time asc')->limit(1)->value('time');
                            $s = $this->getAspectScore(['pid1' => $i, 'pid2' => $phase['id'], 'phase' => $phase['phase_e'], 'type' => 7], $startTime, $endTime);
                            $startTimeBj = strtotime('+8 hour', strtotime($startTime));
                            $endTimeBj = strtotime('+8 hour', strtotime($endTime));
                            if ($phase['phase_e'] === 180)
                            {
                                if ($phase['id'] === ASC)
                                {
                                    $phase['id'] = DES;
                                    $phase['phase_e'] = 0;
                                } elseif ($phase['id'] === MC)
                                {
                                    $phase['id'] = IC;
                                    $phase['phase_e'] = 0;
                                }
                            }
                            $textStatus = $this->transerData(['type' => 7, 'pid1' => $i, 'pid2' => $phase['id'], 'phase' => $phase['phase_e']]);
                            $res[] = [
                                'type' => 7,
                                'tag' => '天象',
                                'title' => $textStatus['text'],
                                'pid' => null,
                                'pid1' => $i,
                                'pid2' => $phase['id'],
                                'phase' => $phase['phase_e'],
                                'in_sign_id' => null,
                                'in_house_id' => null,
                                'state' => 0,
                                'score' => $s,
                                'time' => $nowTime,
                                'start_time' => $startTimeBj,
                                'end_time' => $endTimeBj,
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 1, 1, $i, $phase['phase_e'], $phase['id']),
                                'time_text' => date('Y-m-d H:i:s', $startTimeBj) . ' 到 ' . date('Y-m-d H:i:s', $endTimeBj),
                            ];
                        }
                    }
                }
            }
            $nw_ed_time = microtime(true);
            if (!empty($this->mainRecord))
            {
                $tr_st_tm = microtime(true);
                // 行运数据
                for ($i = 0; $i < 10; $i++)
                {
                    if ($this->doingLimit > 0 && count($res) >= $this->doingLimit)
                    {
                        return $res;
                    }
                    // 换宫数据
                    $startTime = $this->getTransitsHouseTime($i, $transitsData[1]['planets'][$i]['in_house_id'], $transitsData[0]['houses'], $zeroNowStartTime, 0);
                    $endTime = $this->getTransitsHouseTime($i, $transitsData[1]['planets'][$i]['in_house_id'], $transitsData[0]['houses'], $zeroNowStartTime, 1);
                    $startTimeBj = strtotime('+8 hour', $startTime);
                    $endTimeBj = strtotime('+8 hour', $endTime);
                    $textStatus = $this->transerData(['type' => 8, 'pid' => $i, 'in_house_id' => $transitsData[1]['planets'][$i]['in_house_id']]);
                    $res[] = [
                        'type' => 1, // 类型：1=>换座,2=>逆行,3=>日食,4=>月食,5=>新月,6=>满月,7=>相位,8=>换宫,
                        'tag' => '行运',
                        'title' => $textStatus['text'],
                        'pid' => $i,
                        'pid1' => null,
                        'pid2' => null,
                        'phase' => null,
                        'in_sign_id' => null,
                        'in_house_id' => $transitsData[1]['planets'][$i]['in_house_id'],
                        'state' => 0,
                        'score' => 0,
                        'time' => $nowTime,
                        'start_time' => $startTimeBj,
                        'end_time' => $endTimeBj,
                        'status' => $textStatus['status'],
                        // [0]=>1天象、2行运、3三限 [1]=>1相位、2换宫、3换座、4逆行、5日月食 [2&3]=>行星ID[4&5&6]=>相位度数、星座ID、宫位ID[7&8]=>行星ID、逆行2
                        'code' => sprintf("%01d%01d%02d%03d%02d", 2, 2, $i, $transitsData[1]['planets'][$i]['in_house_id'], 0),
                        'time_text' => date('Y-m-d', $startTimeBj) . ' 到 ' . date('Y-m-d', $endTimeBj),
                    ];
//                // 换座数据
//                $startTime = $this->getTransitsSignTime($i, $transitsData[1]['planets'][$i]['in_sign_id'], $zeroNowStartTime, 0);
//                $endTime = $this->getTransitsSignTime($i, $transitsData[1]['planets'][$i]['in_sign_id'], $zeroNowStartTime, 1);
//                $startTimeBj = strtotime('+8 hour', $startTime);
//                $endTimeBj = strtotime('+8 hour', $endTime);
//                $textStatus = $this->transerData(['type' => 1, 'pid' => $i, 'in_sign_id' => $transitsData[1]['planets'][$i]['in_sign_id']]);
//                $res[] = [
//                    'type' => 1, // 类型：1=>换座,2=>逆行,3=>日食,4=>月食,5=>新月,6=>满月,7=>相位,8=>换宫,
//                    'tag' => '行运',
//                    'title' => $textStatus['text'],
//                    'pid' => $i,
//                    'pid1' => null,
//                    'pid2' => null,
//                    'phase' => null,
//                    'in_sign_id' => $transitsData[1]['planets'][$i]['in_sign_id'],
//                    'in_house_id' => null,
//                    'state' => 0,
//                    'score' => 0,
//                    'time' => $nowTime,
//                    'start_time' => $startTimeBj,
//                    'end_time' => $endTimeBj,
//                    'status' => $textStatus['status'],
//                    // [0]=>1天象、2行运、3三限 [1]=>1相位、2换宫、3换座、4逆行、5日月食 [2&3]=>行星ID[4&5&6]=>相位度数、星座ID、宫位ID[7&8]=>行星ID、逆行2
//                    'code' => sprintf("%01d%01d%02d%03d%02d", 2, 3, $i, $transitsData[1]['planets'][$i]['in_sign_id'], 0),
//                    'time_text' => date('Y-m-d', $startTimeBj) . ' 到 ' . date('Y-m-d', $endTimeBj),
//                ];
                    // 相位数据
                    if (!empty($transitsData[1]['planets'][$i]['phase']))
                    {
                        // 行运星体与本命星体的相位
                        foreach ($transitsData[1]['planets'][$i]['phase'] as $phase)
                        {
                            // 行运星是日月水金火 或者 本命星是日月水金火升顶
                            // 由于词条缺失，所以此处仅计算 行运十大行星对本命日月水金火升顶的相位
                            if ($i < 10 && in_array($phase['id'], [0, 1, 2, 3, 4, ASC, MC], true))
                            {
                                // 仅检测合轴相位
                                if (in_array($phase['id'], [ASC, MC], true) && !in_array($phase['phase_e'], [0, 180], true))
                                {
                                    continue;
                                }
                                // 推算开始时间
                                $startTime = $this->getTransitsPhaseTime($i, $transitsData[0]['planets'][$phase['id']]['deg'], $phase['phase_e'], $zeroNowStartTime, 0);
                                // 推算结束时间
                                $endTime = $this->getTransitsPhaseTime($i, $transitsData[0]['planets'][$phase['id']]['deg'], $phase['phase_e'], $zeroNowStartTime, 1);
                                $startTimeBj = strtotime('+8 hour', $startTime);
                                $endTimeBj = strtotime('+8 hour', $endTime);
                                if ($phase['phase_e'] === 180)
                                {
                                    if ($phase['id'] === ASC)
                                    {
                                        $phase['id'] = DES;
                                        $phase['phase_e'] = 0;
                                    } elseif ($phase['id'] === MC)
                                    {
                                        $phase['id'] = IC;
                                        $phase['phase_e'] = 0;
                                    }
                                }
                                $textStatus = $this->transerData(['type' => 7, 'pid1' => $i, 'pid2' => $phase['id'], 'phase' => $phase['phase_e']]);
                                $res[] = [
                                    'type' => 7, // 类型：1=>换座,2=>逆行,3=>日食,4=>月食,5=>新月,6=>满月,7=>相位,8=>换宫,
                                    'tag' => '行运',
                                    'title' => $textStatus['text'],
                                    'pid' => null,
                                    'pid1' => $i,
                                    'pid2' => $phase['id'],
                                    'phase' => $phase['phase_e'],
                                    'in_sign_id' => null,
                                    'in_house_id' => null,
                                    'state' => 0,
                                    'score' => 0,
                                    'time' => $nowTime,
                                    'start_time' => $startTimeBj,
                                    'end_time' => $endTimeBj,
                                    'status' => $textStatus['status'],
                                    // [0]=>1天象、2行运、3三限 [1]=>1相位、2换宫、3换座、4逆行、5日月食 [2&3]=>行星ID[4&5&6]=>相位度数、星座ID、宫位ID[7&8]=>行星ID、逆行2
                                    'code' => sprintf("%01d%01d%02d%03d%02d", 2, 1, $i, $phase['phase_e'], $phase['id']),
                                    'time_text' => date('Y-m-d', $startTimeBj) . ' 到 ' . date('Y-m-d', $endTimeBj),
                                ];
                            }
                        }
                    }
                }
                $tr_ed_tm = microtime(true);
                $th_st_tm = microtime(true);
                // 三限数据
                ini_set('xdebug.max_nesting_level', 10240);// 三限盘递归调用次数上限
                for ($i = 0; $i < 10; $i++)
                {
                    if ($this->doingLimit > 0 && count($res) >= $this->doingLimit)
                    {
                        return $res;
                    }
//                    // 换宫数据
//                    $startEnd = $this->getThirdprogressionHouseTime($i, $thirdprogressedData['planets'][$i]['in_house_id'], $zeroNowStartTime);
//                    $startTime = $startEnd['start'];
//                    $endTime = $startEnd['end'];
//                    $startTimeBj = strtotime('+8 hour', $startTime);
//                    $endTimeBj = strtotime('+8 hour', $endTime);
//                    $textStatus = $this->transerData(['type' => 8, 'pid' => $i, 'in_house_id' => $thirdprogressedData['planets'][$i]['in_house_id']]);
//                    $res[] = [
//                        'type' => 8, // 类型：1=>换座,2=>逆行,3=>日食,4=>月食,5=>新月,6=>满月,7=>相位,8=>换宫,
//                        'tag' => '三限',
//                        'title' => $textStatus['text'],
//                        'pid' => $i,
//                        'pid1' => null,
//                        'pid2' => null,
//                        'phase' => null,
//                        'in_sign_id' => null,
//                        'in_house_id' => $thirdprogressedData['planets'][$i]['in_house_id'],
//                        'state' => 0,
//                        'score' => 0,
//                        'time' => $nowTime,
//                        'start_time' => $startTimeBj,
//                        'end_time' => $endTimeBj,
//                        'status' => $textStatus['status'],
//                        // [0]=>1天象、2行运、3三限 [1]=>1相位、2换宫、3换座、4逆行、5日月食 [2&3]=>行星ID[4&5&6]=>相位度数、星座ID、宫位ID[7&8]=>行星ID、逆行2
//                        'code' => sprintf("%01d%01d%02d%03d%02d", 3, 2, $i, $thirdprogressedData['planets'][$i]['in_house_id'], 0),
//                        'time_text' => date('Y-m-d H:i:s', $startTimeBj) . ' 到 ' . date('Y-m-d H:i:s', $endTimeBj),
//                    ];
                    // 相位数据
                    if (!empty($thirdprogressedData['planets'][$i]['phase']))
                    {
                        // 三限星体的相位
                        foreach ($thirdprogressedData['planets'][$i]['phase'] as $phase)
                        {
                            // 仅检测成相星体ID比当前星体ID数值要大的相位，避免相位重复检测(1-4||4-1)
                            if ($i < $phase['id'] && in_array($i, [0, 1, 2, 3, 4], true))
                            {
                                // 过滤四轴相位  in_array($phase['id'], [ASC, MC], true) && !in_array($phase['phase_e'], [0, 180], true)
                                if ($phase['id'] > 9)
                                {
                                    continue;
                                }
                                // 推算开始时间，推算结束时间
//                                $startEnd = $this->getThirdprogressionPhaseTime2($i, $phase['id'], $phase['phase_e'], $zeroNowStartTime);
//                                $startTime = $startEnd['start'];
//                                $endTime = $startEnd['end'];

                                $startTime = $this->getThirdprogressionPhaseTime($i, $phase['id'], $phase['phase_e'], $zeroNowStartTime, 0);
                                $endTime = $this->getThirdprogressionPhaseTime($i, $phase['id'], $phase['phase_e'], $zeroNowStartTime, 1);
                                $startTimeBj = strtotime('+8 hour', $startTime);
                                $endTimeBj = strtotime('+8 hour', $endTime);
                                if ($phase['phase_e'] === 180)
                                {
                                    if ($phase['id'] === ASC)
                                    {
                                        $phase['id'] = DES;
                                        $phase['phase_e'] = 0;
                                    } elseif ($phase['id'] === MC)
                                    {
                                        $phase['id'] = IC;
                                        $phase['phase_e'] = 0;
                                    }
                                }
                                $textStatus = $this->transerData(['type' => 7, 'pid1' => $i, 'pid2' => $phase['id'], 'phase' => $phase['phase_e']]);
                                $res[] = [
                                    'type' => 7, // 类型：1=>换座,2=>逆行,3=>日食,4=>月食,5=>新月,6=>满月,7=>相位,8=>换宫,
                                    'tag' => '三限',
                                    'title' => $textStatus['text'],
                                    'pid' => null,
                                    'pid1' => $i,
                                    'pid2' => $phase['id'],
                                    'phase' => $phase['phase_e'],
                                    'in_sign_id' => null,
                                    'in_house_id' => null,
                                    'state' => 0,
                                    'score' => 0,
                                    'time' => $nowTime,
                                    'start_time' => $startTimeBj,
                                    'end_time' => $endTimeBj,
                                    'status' => $textStatus['status'],
                                    // [0]=>1天象、2行运、3三限 [1]=>1相位、2换宫、3换座、4逆行、5日月食 [2&3]=>行星ID[4&5&6]=>相位度数、星座ID、宫位ID[7&8]=>行星ID、逆行2
                                    'code' => sprintf("%01d%01d%02d%03d%02d", 3, 1, $i, $phase['phase_e'], $phase['id']),
                                    'time_text' => date('Y-m-d H:i:s', $startTimeBj) . ' 到 ' . date('Y-m-d H:i:s', $endTimeBj),
                                ];
                            }
                        }
                    }
                }
                $th_ed_tm = microtime(true);
            }
//            echo '天象计算时间：' . ($nw_ed_time - $nw_st_time) . 's <br/>' . PHP_EOL;
//            echo '行运计算时间：' . ($tr_ed_tm - $tr_st_tm) . 's <br/>' . PHP_EOL;
//            echo '三限计算时间：' . ($th_ed_tm - $th_st_tm) . 's <br/>' . PHP_EOL;

            // 进行中数据排序
            $res = resort($res, 'end_time', 'ASC');
        }

        return $res;
    }

    /**
     * 将数据转换为可阅读格式
     * @param array $data
     * @return array
     */
    public function transerData($data = []): array
    {
        $planets = ['太阳', '月亮', '水星', '金星', '火星', '木星', '土星', '天王星', '海王星', '冥王星', 17 => '上升', 18 => '天底', 19 => '下降', 20 => '天顶'];
        $signs = ['', '白羊座', '金牛座', '双子座', '巨蟹座', '狮子座', '处女座', '天秤座', '天蝎座', '射手座', '摩羯座', '水瓶座', '双鱼座'];
        $phases = [0 => '合', 60 => '半拱', 90 => '刑', 120 => '拱', 180 => '冲',];
        $text = '';
        $status = 2; // 1=>好（大笑） 2=>平（微笑） 3=>坏（哭）
        if (!empty($data))
        {
            switch ($data['type'])
            {
                // 换座
                case 1:
                    $text .= $planets[$data['pid']] . '进入' . $signs[$data['in_sign_id']];
                    $status = 2;
                    break;
                // 逆行
                case 2:
                    if (isset($data['in_sign_id']) && $data['in_sign_id'])
                    {
                        $text .= $planets[$data['pid']] . '在' . $signs[$data['in_sign_id']] . '逆行';
                    } else
                    {
                        $text .= $planets[$data['pid']] . '逆行';
                    }
                    $status = 3;
                    break;
                // 日食（日月合）
                case 3:
                    $text .= $signs[$data['in_sign_id']] . '日食';
                    $status = 2;
                    break;
                // 月食（日月冲）
                case 4:
                    $text .= $signs[$data['in_sign_id']] . '月食';
                    $status = 2;
                    break;
                // 新月（日月合）
                case 5:
                    $text .= $signs[$data['in_sign_id']] . '新月';
                    $status = 2;
                    break;
                // 满月（日月冲）
                case 6:
                    $text .= $signs[$data['in_sign_id']] . '满月';
                    $status = 2;
                    break;
                // 相位
                case 7:
                    $text .= $planets[$data['pid1']] . $phases[$data['phase']] . $planets[$data['pid2']];
                    /**
                     * 金木参与
                     *   刑日月金木水 平
                     *   刑冲火土冥海天 凶
                     *   合冲拱六分日月金木水 吉
                     *   合拱六分火土冥海天 平
                     * 火土冥海天参与
                     *   刑冲日月水火土天海冥 凶
                     *   合拱六分日月水 平
                     *   合火土天海冥 凶
                     *   拱六分火土天海冥 平
                     * 日月水参与
                     *   拱六分日月水 吉
                     *   刑日月水 凶
                     *   合冲日月水 平
                     */
                    $status = 2;
                    if ($data['pid1'] > $data['pid2'])
                    {
                        $t = $data['pid1'];
                        $data['pid1'] = $data['pid2'];
                        $data['pid2'] = $t;
                    }
                    if (in_array($data['pid1'], [3, 5], false))
                    {
                        if (in_array($data['pid2'], [0, 1, 2, 3, 5], false) && in_array($data['phase'], [0, 60, 120, 180], false))
                        {
                            $status = 1;
                        } elseif (in_array($data['pid2'], [4, 6, 7, 8, 9], false) && in_array($data['phase'], [90, 180], false))
                        {
                            $status = 3;
                        }
                    } elseif (in_array($data['pid1'], [4, 6, 7, 8, 9], false))
                    {
                        if ((in_array($data['pid2'], [0, 1, 2, 4, 6, 7, 8, 9], false) && in_array($data['phase'], [90, 180], false))
                            || (in_array($data['pid2'], [4, 6, 7, 8, 9], false) && $data['phase'] == 0))
                        {
                            $status = 3;
                        }
                    } elseif (in_array($data['pid1'], [0, 1, 2], false))
                    {
                        if (in_array($data['pid2'], [0, 1, 2], false))
                        {
                            if (in_array($data['phase'], [60, 120], false))
                            {
                                $status = 1;
                            } elseif ($data['phase'] == 90)
                            {
                                $status = 3;
                            }
                        }
                    }
                    break;
                // 换宫
                case 8:
                    $text .= $planets[$data['pid']] . '进入' . $data['in_house_id'] . '宫';
                    /**
                     * 金木 吉
                     * 火土冥海 凶
                     * 日月水天 平
                     */
                    switch ($data['pid'])
                    {
                        case 0:
                        case 1:
                        case 2:
                        case 7:
                            $status = 2;
                            break;
                        case 3:
                        case 5:
                            $status = 1;
                            break;
                        case 4:
                        case 6:
                        case 8:
                        case 9:
                            $status = 3;
                            break;
                        default:
                            $status = 2;
                            break;
                    }
                    break;
            }
        }
        return ['text' => $text, 'status' => $status];
    }

    /**
     * 获取天象 换座、逆行、相位
     * @return array
     */
    protected function getDataFromNow(): array
    {
        $res = [];
        $execPrefix = config('astrolog.prefix');
        $astro = Astrolog::getInstance()
            ->setAdvance($this->advance)
            ->setExecPrefix($execPrefix)
            ->setIsAstrolabe(true)
            ->setUserSetting($this->setting)
            ->setVersion(2)
            ->setGetDatas(['natal']);
        if (!empty($this->mainRecord))
        {
            $astro = $astro->setRecode1($this->mainRecord)->getAstroDatas();
            // 获取本命盘数据
            $natalData = json_decode(json_encode($astro->getDatas('natal')), true);
        }

        // 东八区的时间戳，数据库中存的是零时区的，所以需要转换, $advanceTime['ut_timestamp']为0时区时间
        $advanceTime = $astro->getAdvance();
        $nowYmd = date('Ymd', strtotime('+8hour', $advanceTime['ut_timestamp']));
        // 查询 天象 换座、逆行、日月食数据
        $dayAstroChange = (new AstroChange())->whereTime('time', 'between', [date('Y-m-d H:i:s', $advanceTime['ut_timestamp']), date('Y-m-d H:i:s', strtotime('+1day', $advanceTime['ut_timestamp']))])
            ->where('type', 'in', [1, 2, 3, 4])->select();
        $dayAstroChange = json_decode(json_encode($dayAstroChange), true);

        // 感受度计算
        //	【天象】相位（月相、日月食以日月相位看待）相位计算按精确成相点来计算数据
        //		相位中星体与本命星体成相
        //			按成相次数和星体重要性计算
        //			本命星体重要性指数*容许系数*相位系数=单相易感度
        //			各单相易感度相加/2+最高单相易感度/2
        //			指数
        //				本命星体重要性
        //					日月命度10，金水火6，木土2，天海冥1，命主4，中天7（只论上升中天，不论下降天底）
        //				容许系数
        //					略
        //				相位系数
        //					略
        //		落宫（如有合轴效果不计落宫）看天象星体落入本命的宫位
        //			角
        //				1-4，,10-4，,7-3，,4-3
        //			续
        //				2-2，,8-2，,5-3，11-3
        //			果
        //				3-1，,6-1，,9-2，,12-1
        //		参与相位的星体为命主星
        //			7
        //		相位部分+落宫部分+命主星部分为最终结果，但需调整为百分比，百分比不超过99
        //	本命星体重要性:日月升10，金水火6，木土2，天海冥1，命主4，中天7（只论上升中天，不论下降天底）
        $x = [0 => 10, 1 => 10, 2 => 6, 3 => 6, 4 => 6, 5 => 2, 6 => 2, 7 => 1, 8 => 1, 9 => 1, ASC => 10, MC => 7, 'h1r' => 4];
        //	相位系数
        $y = [0 => 1, 60 => 0.7, 90 => 0.8, 120 => 0.8, 180 => 0.9];
        //	容许系数： <0.5=1;<1=0.95;<1.5=0.85; 0.7
        // 获取北京时间该天内的精准成相数据，结果中的时间为0时区时间
        $dayAspectList = Db::table('wechat_backup_07_18_14_43_00.app_aspect_change')
            ->whereTime('time', 'between', [date('Y-m-d H:i:s', $advanceTime['ut_timestamp']), date('Y-m-d H:i:s', strtotime('+1day', $advanceTime['ut_timestamp']))])
            ->where('state', '<>', 2)->select();
        $dayAspectList = json_decode(json_encode($dayAspectList, true), true);
        foreach ($dayAspectList as $k1 => $v1)
        {
            if ($v1['state'] == 1)
            {
                $start_time = $v1['time'];
                $end_time = Db::table('wechat_backup_07_18_14_43_00.app_aspect_change')->whereTime('time', '>', $v1['time'])
                    ->where('pid1', $v1['pid1'])
                    ->where('pid2', $v1['pid2'])
                    ->where('phase', $v1['phase'])
                    ->where('state', 3)->order('time ASC')->limit(1)->value('time');
            } else
            {
                $start_time = Db::table('wechat_backup_07_18_14_43_00.app_aspect_change')->whereTime('time', '<', $v1['time'])
                    ->where('pid1', $v1['pid1'])
                    ->where('pid2', $v1['pid2'])
                    ->where('phase', $v1['phase'])
                    ->where('state', 1)->order('time DESC')->limit(1)->value('time');
                $end_time = $v1['time'];
            }
            $s = $this->getAspectScore($v1, $start_time, $end_time);
            $textStatus = $this->transerData($v1);
            if ($this->changeType === 1)
            {
                $startTimeBj = strtotime('+8 hour', strtotime($start_time));
                $endTimeBj = strtotime('+8 hour', strtotime($end_time));
                $startYmd = date('Ymd', $startTimeBj);
                $endYmd = date('Ymd', $endTimeBj);
                $timeBj = $v1['state'] * 1 === 1 ? $startTimeBj : $endTimeBj;
                $res[] = [
                    'type' => 1,
                    'tag' => '天象',
                    'title' => $textStatus['text'],
                    'pid' => null,
                    'pid1' => $v1['pid1'],
                    'pid2' => $v1['pid2'],
                    'phase' => $v1['phase'],
                    'in_sign_id' => null,
                    'in_house_id' => null,
                    'state' => (int)$v1['state'],
                    'score' => $s,
                    'time' => $timeBj,
                    'start_time' => $startTimeBj,
                    'end_time' => $endTimeBj,
                    'status' => $textStatus['status'],
                    'code' => sprintf("%01d%01d%02d%03d%02d", 1, 1, $v1['pid1'], $v1['phase'], $v1['pid2']),
                    'time_text' => date('Y-m-d H:i:s', $startTimeBj) . '~' . date('Y-m-d H:i:s', $endTimeBj),
                ];
            }
        }
        foreach ($dayAstroChange as $kk1 => $vv1)
        {
            if (in_array($vv1['type'], [3, 4], true))
            {
                $start_time = strtotime($vv1['time']);
                $end_time = json_decode($vv1['extend'], true)['end'];
                $s = $this->getAspectScore($vv1, $start_time, $end_time);
                $textStatus = $this->transerData($vv1);
                // 星象变动仅展示当天的
                if ($this->changeType === 1)
                {
                    $startTimeBj = strtotime('+8 hour', $start_time);
                    $endTimeBj = strtotime('+8 hour', $end_time);
                    $startYmd = date('Ymd', $startTimeBj);
                    $endYmd = date('Ymd', $endTimeBj);
                    if ($startYmd === $nowYmd)
                    {
                        $res[] = [
                            'type' => 1,
                            'tag' => '天象',
                            'title' => $textStatus['text'],
                            'pid' => $vv1['pid'],
                            'pid1' => null,
                            'pid2' => null,
                            'phase' => null,
                            'in_sign_id' => $vv1['in_sign_id'],
                            'in_house_id' => null,
                            'state' => 1,
                            'score' => $s,
                            'time' => $startTimeBj,
                            'start_time' => $startTimeBj,
                            'end_time' => $endTimeBj,
                            'status' => $textStatus['status'],
                            'code' => sprintf("%01d%01d%02d%03d%02d", 1, 1, $vv1['pid'], $vv1['in_sign_id'], 0),
                            'time_text' => date('Y-m-d H:i:s', $startTimeBj),
                        ];
                    }
                    if ($endYmd === $nowYmd)
                    {
                        $res[] = [
                            'type' => 1,
                            'tag' => '天象',
                            'title' => $textStatus['text'],
                            'pid' => $vv1['pid'],
                            'pid1' => null,
                            'pid2' => null,
                            'phase' => null,
                            'in_sign_id' => $vv1['in_sign_id'],
                            'in_house_id' => null,
                            'state' => 3,
                            'score' => $s,
                            'time' => $endTimeBj,
                            'start_time' => $startTimeBj,
                            'end_time' => $endTimeBj,
                            'status' => $textStatus['status'],
                            'code' => sprintf("%01d%01d%02d%03d%02d", 1, 1, $vv1['pid'], $vv1['in_sign_id'], 0),
                            'time_text' => date('Y-m-d H:i:s', $endTimeBj),
                        ];
                    }
                }
            }
        }

        //	【天象】逆行
        //		计算逆行起点和终点
        //			判断本命是否有星体跟起点终点成相位（此处只看逆行星体的）
        //				本命星体重要性指数*容许系数*相位系数*2=易感度
        //			判断本命是否有星体不跟起点终点成相位，但在成相位的区间上（与起点终点之间的任一点成相）
        //				本命星体重要性指数*容许系数*相位系数*=易感度
        //			判断逆行行经宫位
        //				角
        //					1-4，,10-4，,7-3，,4-3
        //				续
        //					2-2，,8-2，,5-3，11-3
        //				果
        //					3-1，,6-1，,9-2，,12-1
        //			逆行的星体为命主星
        //				7
        //			四项相加，最终调整为百分比，百分比不超过99
        if (!empty($dayAstroChange))
        {
            $max = 20;
            foreach ($dayAstroChange as $k2 => $v2)
            {
                // 顺逆行变换
                if ($v2['type'] * 1 === 2)
                {
                    $map = ['time' => ['>', $v2['time']], 'type' => 2, 'pid' => $v2['pid']];
                    /**
                     * 开始逆行
                     * speed 1=>顺行2=>逆行
                     */
                    if ($v2['speed'] === 2)
                    {
                        // 获取终点数据
                        $map['time'] = ['>', $v2['time']];
                        $retData = (new AstroChange())->where($map)->order('time ASC')->limit(1)->value('time');

                        $startTime = strtotime($v2['time']);
                        $endTime = strtotime($retData);
                    } // 恢复顺行
                    else
                    {
                        // 获取起点数据
                        $map['time'] = ['<', $v2['time']];
                        $retData = (new AstroChange())->where($map)->order('time DESC')->limit(1)->value('time');

                        $startTime = strtotime($retData);
                        $endTime = strtotime($v2['time']);
                    }
                    // 计算逆行感受度 得分
                    $s = $this->getRetroScore($v2, $startTime, $endTime, $max);
                    $textStatus = $this->transerData($v2);
                    if ($this->changeType === 1)
                    {
                        $startTimeBj = strtotime('+8 hour', $startTime);
                        $endTimeBj = strtotime('+8 hour', $endTime);
                        $startYmd = date('Ymd', $startTimeBj);
                        $endYmd = date('Ymd', $endTimeBj);
                        if ($startYmd === $nowYmd)
                        {
                            $res[] = [
                                'type' => $v2['type'],
                                'tag' => '天象',
                                'title' => $textStatus['text'],
                                'pid' => $v2['pid'],
                                'pid1' => null,
                                'pid2' => null,
                                'phase' => null,
                                'in_sign_id' => null, // $v2['in_sign_id']
                                'in_house_id' => null,
                                'state' => 1,
                                'score' => $s,
                                'time' => $startTimeBj,
                                'start_time' => $startTimeBj,
                                'end_time' => $endTimeBj,
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 1, 4, $v2['pid'], 0, 2),
                                'time_text' => date('Y-m-d H:i:s', $startTimeBj),
                            ];
                        }
                        if ($endYmd === $nowYmd)
                        {
                            $res[] = [
                                'type' => $v2['type'],
                                'tag' => '天象',
                                'title' => $textStatus['text'],
                                'pid' => $v2['pid'],
                                'pid1' => null,
                                'pid2' => null,
                                'phase' => null,
                                'in_sign_id' => null, // $v2['in_sign_id']
                                'in_house_id' => null,
                                'state' => 3,
                                'score' => $s,
                                'time' => $endTimeBj,
                                'start_time' => $startTimeBj,
                                'end_time' => $endTimeBj,
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 1, 4, $v2['pid'], 0, 2),
                                'time_text' => date('Y-m-d H:i:s', $endTimeBj),
                            ];
                        }
                    }
                }
            }
        }

        //	【天象】星体入座
        //		计算该星座对案主的影响力
        //			该星座上的重要星体和虚点：日月10，ASC10，MC9，金水火7，下降天底6，命主4，木土2，南北交2
        //			累计相加
        //			调整为百分比，最高不超过99
        if (!empty($dayAstroChange))
        {
            $planets = ['0' => 10, '1' => 10, '2' => 7, '3' => 7, '4' => 7, '5' => 2, '6' => 7, IC => 6, DES => 6, '12' => 2, '16' => 2, 'h1p' => 4];
            // 总分
            $max = 30;// array_sum($planets)
            foreach ($dayAstroChange as $k3 => $v3)
            {
                $s = 0;
                // 行星换座
                if ($v3['type'] * 1 === 1)
                {
                    // 获取该星体下次换座的时间点
                    $endTime = Db::table('wechat_backup_07_18_14_43_00.app_astro_change')
                        ->whereTime('time', '>', $v3['time'])
                        ->where('pid', $v3['pid'])
                        ->where('type', 1)
                        ->order('time ASC')->limit(1)->value('time');
                    $inSign = $v3['in_sign_id'] * 1;
                    if (!empty($this->mainRecord))
                    {
                        /**
                         * 检测该星座上的星体
                         * 日月10，ASC10，MC9，金水火7，下降天底6，命主4，木土2，南北交2
                         */
                        foreach ($planets as $key => $value)
                        {
                            if (($key === 'h1p' && $natalData['houses'][1]['protect_ancient_insign_id'] === $inSign)
                                || ($key !== 'h1p' && $natalData['planets'][$key]['in_sign_id'] === $inSign))
                            {
                                $s += $value;
                            }
                        }
                    }

                    $s /= $max;
                    if ($s > 0.99)
                    {
                        $s = 0.99;
                    } elseif ($s < 0.05)
                    {
                        $s = 0.05;
                    }

                    $textStatus = $this->transerData($v3);
                    if ($this->changeType === 1)
                    {
                        $startTimeBj = strtotime('+8 hour', strtotime($v3['time']));
                        $endTimeBj = strtotime('+8 hour', strtotime($endTime));
                        $startYmd = date('Ymd', $startTimeBj);
                        $endYmd = date('Ymd', $endTimeBj);
                        if ($startYmd === $nowYmd)
                        {
                            $res[] = [
                                'type' => $v3['type'],
                                'tag' => '天象',
                                'title' => $textStatus['text'],
                                'pid' => $v3['pid'],
                                'pid1' => null,
                                'pid2' => null,
                                'phase' => null,
                                'in_sign_id' => $inSign,
                                'in_house_id' => null,
                                'state' => 1,
                                'score' => $s,
                                'time' => $startTimeBj,
                                'start_time' => $startTimeBj,
                                'end_time' => $endTimeBj,
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 1, 3, $v3['pid'], $v3['in_sign_id'], 0),
                                'time_text' => date('Y-m-d H:i:s', $startTimeBj),
                            ];
                        }
                        if ($endYmd === $nowYmd)
                        {
                            $res[] = [
                                'type' => $v3['type'],
                                'tag' => '天象',
                                'title' => $textStatus['text'],
                                'pid' => $v3['pid'],
                                'pid1' => null,
                                'pid2' => null,
                                'phase' => null,
                                'in_sign_id' => $inSign,
                                'in_house_id' => null,
                                'state' => 3,
                                'score' => $s,
                                'time' => $endTimeBj,
                                'start_time' => $startTimeBj,
                                'end_time' => $endTimeBj,
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 1, 3, $v3['pid'], $v3['in_sign_id'], 0),
                                'time_text' => date('Y-m-d H:i:s', $endTimeBj),
                            ];
                        }
                    }
                }
            }
        }
        return $res;
    }

    /**
     * 获取行运
     *  计算入宫,相位（入相时间、结束相位时间）
     */
    public function getDataFromTransits()
    {
        $res = [];

        $execPrefix = config('astrolog.prefix');
        $astro = Astrolog::getInstance()
            ->setRecode1($this->mainRecord)
            ->setAdvance($this->advance)
            ->setExecPrefix($execPrefix)
            ->setIsAstrolabe(true)
            ->setUserSetting($this->setting)
            ->setVersion(2)
            ->setGetDatas(['natal'])
            ->getAstroDatas();
        // 获取本命盘数据
        $natalData = json_decode(json_encode($astro->getDatas('natal')), true);
        // 行运起始时间
        $advanceTime = $astro->getAdvance();

        // 遍历10大行星
        for ($i = 0; $i < 10; $i++)
        {
            /**
             * 获取入宫数据
             */
            $this->getTransitsHouseChangeData($res, $advanceTime['ut_timestamp'], $natalData['houses'], $i, 1440, '1m');
            /**
             * 获取相位数据
             */
            $this->getTransitsPhaseData($res, $advanceTime['ut_timestamp'], $natalData['planets'], $i);
        }

        return $res;
    }

    /**
     * 获取三限
     *  计算入宫,相位（入相时间、结束相位时间）
     */
    public function getDataFromProgression(): array
    {
        $res = [];
        // 当天0点的推进时间，转换成0时区后的
        $advanceTime = Astrolog::getInstance()->setAdvance($this->advance)->getAdvance();
        /**
         * 取用户0点三限盘，和次日0点三限盘，对比看形成了哪些新相位（或结束了哪些）、新落宫，
         * 两盘转化成A时间点的天象，B时间的天象（出生地），计算AB两个时间点之间的天象变化找到某相位或入宫变化起点（或终点）C，将时间C转化为该用户的三限时间点D，输出D
         */
        $startTime = $advanceTime['ut_timestamp'] - 3600; // 往前推1小时
        $endTime = $advanceTime['ut_timestamp'] + 86400; //
        $thirdprogressed = [];
        for ($l = $startTime; $l <= $endTime; $l += 3600)
        {
            $this->setAdvance(date('Y-m-d H:i:s', $l));
            $astro = Astrolog::getInstance()->setAdvance($this->advance)->setGetDatas(['thirdprogressed'])->getAstroDatas();
            $thirdprogressed[] = json_decode(json_encode($astro->getDatas('thirdprogressed')), true);
        }
        foreach ($thirdprogressed as $k1 => $v1)
        {
            if ($k1 === 0) continue;
            $before = $thirdprogressed[$k1 - 1];
            $now = $thirdprogressed[$k1];
            $caclTime = $startTime + ($k1 - 1) * 3600;// 触发时间为上一小时
//            $aa1[] = date('Y-m-d H:i:s', $caclTime);
            for ($i = 0; $i < 10; $i++)
            {
                $t1House = $before['planets'][$i]['in_house_id'];
                $t2House = $now['planets'][$i]['in_house_id'];
                // 发现星体落宫发生变化 测试时间：time=2022-12-11
                if ($t1House !== $t2House)
                {
                    $textStatus = $this->transerData(['type' => 8, 'pid' => $i, 'in_house_id' => $t2House]);
                    $res[] = [
                        'type' => 8,
                        'tag' => '三限',
                        'title' => $textStatus['text'],
                        'pid' => $i,
                        'pid1' => null,
                        'pid2' => null,
                        'phase' => null,
                        'in_sign_id' => null,
                        'in_house_id' => $t2House,
                        'state' => 1,
                        'score' => null,
                        'time' => strtotime('+8 hour', $caclTime),
                        'status' => $textStatus['status'],
                        'code' => sprintf("%01d%01d%02d%03d%02d", 3, 2, $i, $t2House, 0),
                        'time_text' => date('Y-m-d H:i:s', strtotime('+8 hour', $caclTime)),
                    ];
                }
                if ($now['planets'][$i]['phase'] === null)
                {
                    $now['planets'][$i]['phase'] = [];
                }
                if ($before['planets'][$i]['phase'] === null)
                {
                    $before['planets'][$i]['phase'] = [];
                }
                // 日月水金火木土天海冥升顶 互相之间的相位
                // 当前有的相位，前一次没有的（开始成相）
                $diffKeys1 = array_diff_key($now['planets'][$i]['phase'], $before['planets'][$i]['phase']);
                // 前一次有的相位，当前没有的（结束成相）
                $diffKeys2 = array_diff_key($before['planets'][$i]['phase'], $now['planets'][$i]['phase']);
                /**
                 * 检测星体相位差集，相位变化
                 */
                foreach ($diffKeys1 as $k2 => $v2)
                {
                    $ids = explode('-', $k2);
                    if ($ids[0] >= $ids[1] || ($ids[1] >= 17 && !in_array($v2['phase_e'], [0, 180], false)))
                    {
                        continue;
                    }
                    $textStatus = $this->transerData(['type' => 7, 'pid1' => $ids[0], 'pid2' => $ids[1], 'phase' => $v2['phase_e']]);
                    $res[] = [
                        'type' => 8,
                        'tag' => '三限',
                        'title' => $textStatus['text'],
                        'pid' => null,
                        'pid1' => (int)$ids[0],
                        'pid2' => (int)$ids[1],
                        'phase' => $v2['phase_e'],
                        'state' => 1, // 0=>不成相,1=>开始成相,2=>精准成相,3=>结束成相
                        'in_sign_id' => null,
                        'in_house_id' => null,
                        'score' => null,
                        'time' => strtotime('+8 hour', $caclTime),
                        'status' => $textStatus['status'],
                        'code' => sprintf("%01d%01d%02d%03d%02d", 3, 1, $ids[0], $v2['phase_e'], $ids[1]),
                        'time_text' => date('Y-m-d H:i:s', strtotime('+8 hour', $caclTime)),
                    ];
                }
                foreach ($diffKeys2 as $k3 => $v3)
                {
                    $ids = explode('-', $k3);
                    if ($ids[0] >= $ids[1] || ($ids[1] >= 17 && !in_array($v3['phase_e'], [0, 180], false)))
                    {
                        continue;
                    }
                    $textStatus = $this->transerData(['type' => 7, 'pid1' => $ids[0], 'pid2' => $ids[1], 'phase' => $v3['phase_e']]);
                    $res[] = [
                        'type' => 8,
                        'tag' => '三限',
                        'title' => $textStatus['text'],
                        'pid' => null,
                        'pid1' => (int)$ids[0],
                        'pid2' => (int)$ids[1],
                        'phase' => $v3['phase_e'],
                        'state' => 3, // 0=>不成相,1=>开始成相,2=>精准成相,3=>结束成相
                        'in_sign_id' => null,
                        'in_house_id' => null,
                        'score' => null,
                        'time' => strtotime('+8 hour', $caclTime),
                        'status' => $textStatus['status'],
                        'code' => sprintf("%01d%01d%02d%03d%02d", 3, 1, $ids[0], $v3['phase_e'], $ids[1]),
                        'time_text' => date('Y-m-d H:i:s', strtotime('+8 hour', $caclTime)),
                    ];
                }
            }
        }

        return $res;
    }

    /**
     * 计算度数差，用于相位检测
     * @param $deg1
     * @param $deg2
     * @return int
     */
    protected function getDiffDeg($deg1, $deg2)
    {
        if ($deg1 >= $deg2)
        {
            $diff = $deg1 - $deg2;
        } else
        {
            $diff = $deg2 - $deg1;
        }
        if ($diff > 180)
        {
            $diff = 360 - $diff;
        }
        return $diff;
    }

    /**
     * 检测相位 入相、精准成相、出相位
     * @param $res array 结果数组
     * @param $startTime int 第一条数据的时间
     * @param $planets array 需要进行相位检测的星体度数列表
     * @param $pid int 行星ID
     * param $n int 要计算的数据数量
     * param $s string 每条数据之间的间隔 1m=>每分钟一条数据 1s=>每秒一条数据
     */
    protected function getTransitsPhaseData(&$res, $startTime, $planets, $pid)
    {
        // , int $n = 1440, string $s = '1m'
        // 需要参与计算的星体ID列表
        $aspPlanets = [0, 1, 2, 3, 4, ASC, MC];
        // 需要检查的相位列表
        $asps = [0, 60, 90, 120, 180];
        if ($pid === 1)
        {
//            $asps =  [0, 90, 180];
        }
        // 行运相位容许度
        $orbSetting = $this->setting['transits']['asp_orb_all'];
        // 成相度数范围
        $aspRange = [];
        // 开始计算本命星体成相度数范围
        foreach ($aspPlanets as $l)
        {
            foreach ($asps as $m)
            {
                // 此处四轴的相位只看合轴 !in_array($m, [0, 180], true)
                if (in_array($l, [ASC, MC], true) && !in_array($m, [0, 180], true))
                {
                    continue;
                }
                $aspRange[$l][$m] = $this->getRangeOfPhaseDeg($planets[$l]['deg'], $m, $orbSetting[$m]);
            }
        }

        $n = 24;
        $s = '1h';

        // 当前星体一天内每分钟的行星度数
        $utData = Astrolog::getInstance()->getPlanetDegByTimestamp($pid, $startTime, $n, $s, 'l');
        if (!empty($utData))
        {
            $x = $s === '1h' ? 3600 : 1;
//            $x = $s === '1m' ? 60 : 1;
            foreach ($utData as $k1 => $v1)
            {
                if ($k1 === 0) continue;
                $caclTime = $startTime + $k1 * $x;
                $nowMinuteDeg = (float)$v1;
                $preMinuteDeg = isset($utData[$k1 - 1]) ? (float)$utData[$k1 - 1] : -999;
                $nextMinuteDeg = isset($utData[$k1 + 1]) ? (float)$utData[$k1 + 1] : -999;
                $preSecondDeg = Astrolog::getInstance()->getPlanetDegByTimestamp($pid, $caclTime - 1, 1, '1s');
                $nowMinutePhaseResult = -1;
                foreach ($aspRange as $k2 => $v2)
                {
                    // 行运星是日月水金火 或者 本命星是日月水金火升顶
                    // 由于词条缺失，所以此处仅计算 行运十大行星对本命日月水金火升顶的相位
                    if ($pid > 10 || !in_array($k2, [0, 1, 2, 3, 4, ASC, MC], true))
                    {
                        continue;
                    }
                    // 获取成相度数，不是-1则代表成相
                    $nowMinutePhaseResult = $this->isInPhaseRange($nowMinuteDeg, $v2);
                    if ($nowMinutePhaseResult !== -1)
                    {
                        /**
                         * 先检测上一分钟是否已经成相
                         *    若已成相：
                         *       检测前后各一分钟，当前分钟相位的误差是否最小，检测当前分钟前1秒，比较出最小的误差，得出精准成相发生的具体时间
                         *    若不成相：
                         *       检测上一秒钟是否成相，若成，则在上一分钟开始成相，否则：当前分钟开始成相
                         */
                        $preMinutePhaseResult = $this->isInPhaseRange($preMinuteDeg, $v2);
                        // 当前分钟成相，且上一分钟不成相，准备检测开始成相
                        if ($preMinutePhaseResult === -1)
                        {
                            // 检测上一秒钟是否成相
                            $preSecondPhaseResult = $this->isInPhaseRange($preSecondDeg, $v2);
                            if ($preSecondPhaseResult === -1)
                            {
                                // 上一秒钟不成相，开始成相时间在当前小时
                                $time = $caclTime;
                            } else
                            {
                                // 上一秒钟成相，开始成相时间在上一小时
                                $time = $caclTime - $x;
                            }
                            $pid2 = $k2;
                            if ($nowMinutePhaseResult === 180 && in_array($k2, [ASC, MC], true))
                            {
                                if ($k2 === ASC)
                                {
                                    $pid2 = DES;
                                } elseif ($k2 === MC)
                                {
                                    $pid2 = IC;
                                }
                                $nowMinutePhaseResult = 0;
                            }
                            $textStatus = $this->transerData(['type' => 7, 'pid1' => $pid, 'pid2' => $pid2, 'phase' => $nowMinutePhaseResult]);
                            $res[] = [
                                'type' => 8,
                                'tag' => '行运',
                                'title' => $textStatus['text'],
                                'pid' => null,
                                'pid1' => $pid,
                                'pid2' => $pid2,
                                'phase' => $nowMinutePhaseResult,
                                'state' => 1, // 0=>不成相,1=>开始成相,2=>精准成相,3=>结束成相
                                'in_sign_id' => null,
                                'in_house_id' => null,
                                'score' => null,
                                'time' => strtotime('+8 hour', $time),
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 2, 1, $pid, $nowMinutePhaseResult, $pid2),
                                'time_text' => date('Y-m-d H:i:s', strtotime('+8 hour', $time)),
                            ];
                            break;
                        } else
                        {

                        }
                    } else
                    {
                        /**
                         * 当前分钟不成相
                         *   若上一分钟成相，开始检测结束成相
                         *      检测上一秒是否成相
                         *          若成相：当前分钟结束成相
                         *          不成相：上一分钟结束成相
                         */
                        $preMinutePhaseResult = $this->isInPhaseRange($preMinuteDeg, $v2);
                        if ($preMinutePhaseResult !== -1)
                        {
                            // 检测上一秒钟是否成相
                            $preSecondPhaseResult = $this->isInPhaseRange($preSecondDeg, $v2);
                            if ($preSecondPhaseResult === -1)
                            {
                                // 上一秒钟成相，结束成相时间在当前小时
                                $time = $caclTime;
                            } else
                            {
                                // 上一秒钟不成相，结束成相时间在上一小时
                                $time = $caclTime - $x;
                            }
                            $pid2 = $k2;
                            if ($preMinutePhaseResult === 180 && in_array($k2, [ASC, MC], true))
                            {
                                if ($k2 === ASC)
                                {
                                    $pid2 = DES;
                                } elseif ($k2 === MC)
                                {
                                    $pid2 = IC;
                                }
                                $preMinutePhaseResult = 0;
                            }
                            $textStatus = $this->transerData(['type' => 7, 'pid1' => $pid, 'pid2' => $pid2, 'phase' => $preMinutePhaseResult]);
                            $res[] = [
                                'type' => 8,
                                'tag' => '行运',
                                'title' => $textStatus['text'],
                                'pid' => null,
                                'pid1' => $pid,
                                'pid2' => $pid2,
                                'phase' => $preMinutePhaseResult,
                                'state' => 3, // 0=>不成相,1=>开始成相,2=>精准成相,3=>结束成相
                                'in_sign_id' => null,
                                'in_house_id' => null,
                                'score' => null,
                                'time' => strtotime('+8 hour', $time),
                                'status' => $textStatus['status'],
                                'code' => sprintf("%01d%01d%02d%03d%02d", 2, 1, $pid, $preMinutePhaseResult, $pid2),
                                'time_text' => date('Y-m-d H:i:s', strtotime('+8 hour', $time)),
                            ];
                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * 判断换宫的时间
     * @param $res array 结果数组
     * @param $startTime int 初始时间
     * @param $houseList array 宫位的数据列表
     * @param $pid int 行星ID
     * @param $n int 要计算的数据数量
     * @param $s string 每条数据之间的间隔 1m=>每分钟一条数据 1s=>每秒一条数据
     */
    protected function getTransitsHouseChangeData(&$res, $startTime, $houseList, $pid, int $n = 1440, string $s = '1m')
    {
        // 当前星体一天内每分钟的行星度数
        $utData = Astrolog::getInstance()->getPlanetDegByTimestamp($pid, $startTime, $n, $s, 'l');
        if (!empty($utData))
        {
            $x = $s === '1m' ? 60 : 1;
            foreach ($utData as $k1 => $v1)
            {
                $caclTime = $startTime + $k1 * $x;
                $v1 = (float)$v1;
                $nowHouse = Astrolog::getInstance()->inWhichHouse($v1, $houseList);
                $preHouse = isset($utData[$k1 - 1]) ? Astrolog::getInstance()->inWhichHouse((float)$utData[$k1 - 1], $houseList) : -999;
                // 当前宫位发生变化
                if ($preHouse !== -999 && $preHouse !== $nowHouse)
                {
                    if ($s === '1s')
                    {
                        $textStatus = $this->transerData(['type' => 8, 'pid' => $pid, 'in_house_id' => $nowHouse]);
                        $res[] = [
                            'type' => 8,
                            'tag' => '行运',
                            'title' => $textStatus['text'],
                            'pid' => $pid,
                            'pid1' => null,
                            'pid2' => null,
                            'phase' => null,
                            'in_sign_id' => null,
                            'in_house_id' => $nowHouse,
                            'state' => 1,
                            'score' => null,
                            'time' => strtotime('+8 hour', $caclTime),
                            'status' => $textStatus['status'],
                            'code' => sprintf("%01d%01d%02d%03d%02d", 2, 2, $pid, $nowHouse, 0),
                            'time_text' => date('Y-m-d H:i:s', strtotime('+8 hour', $caclTime)),
                        ];
                    } else
                    {
                        $this->getTransitsHouseChangeData($res, $caclTime - 60, $houseList, $pid, 120, '1s');
                    }
                }
            }
        }
    }

    /**
     * 计算固定度数的成相区间范围
     * 测试案例 $deg = 1，$orb = 2 计算五个相位的区间值
     * $deg = 1, $phase = 0, $orb = 2,
     *    $real = 1,  $max = 3, $min = 359, [0, 3], [359, 360]
     * $deg = 1, $phase = 60, $orb = 2,
     *    $real = 61, $max = 63, $min = 59, [59, 63]
     *    $real = 301, $max = 303, $min = 299, [299, 303]
     * $deg = 1, $phase = 90, $orb = 2,
     *    $real = 91, $max = 93, $min = 89, [89, 93]
     *    $real = 271, $max = 273, $min = 269, [269, 273]
     * $deg = 1, $phase = 120, $orb = 2,
     *    $real = 121, $max = 123, $min = 119, [119, 123]
     *    $real = 241, $max = 243, $min = 239, [239, 243]
     * $deg = 1, $phase = 180, $orb = 2,
     *    $real = 181 $max = 183, $min = 179, [179, 183]
     * @param $deg float 给定一个度数
     * @param $phase int 给定一个相位
     * @param $orb float 给定一个相位容许度
     * @return array
     */
    protected function getRangeOfPhaseDeg($deg, $phase, $orb)
    {
        $range = [];
        $realDeg[] = $deg + $phase;
        /**
         * 只有0度和180度的精准成相度数唯一，其他相位的精准成相度数有两个
         */
        if ($phase !== 0 && $phase !== 180)
        {
            $realDeg[] = $deg - $phase;
        }
        // 遍历精准成相度数
        foreach ($realDeg as $k1 => $v1)
        {
            // 容许度计算
            $max = $v1 + $orb;
            $min = $v1 - $orb;
            if ($max > 360)
            {
                $max -= 360;
            } elseif ($max < 0)
            {
                $max += 360;
            }
            if ($min > 360)
            {
                $min -= 360;
            } elseif ($min < 0)
            {
                $min += 360;
            }
            // 处理特殊情况
            if ($min > $max)
            {
                $range[] = ['min' => $min, 'max' => 360];
                $range[] = ['min' => 0, 'max' => $max];
            } else
            {
                $range[] = ['min' => $min, 'max' => $max];
            }
        }
        return $range;
    }

    /**
     * 判断度数是否在成相范围内
     * @param $deg
     * @param $range
     * @return int
     */
    protected function isInPhaseRange($deg, $range): int
    {
        if (!empty($range))
        {
            // $k1 相位度数
            foreach ($range as $k1 => $v1)
            {
                // 开始遍历每个成相区间
                foreach ($v1 as $k2 => $v2)
                {
                    if ($deg >= $v2['min'] && $deg <= $v2['max'])
                    {
                        return $k1;
                    }
                }
            }
        }
        return -1;
    }

    /**
     * 递归获取指定精度的相位数据
     * @param array $res 结果数组
     * @param int $startTime 开始时间的时间戳
     * @param array $planets 行星数据
     * @param int $pid 行星ID
     * @param string $need 需要精确的粒度
     * @param string $s 当前粒度
     * @param callable $callback
     */
    protected function getPhaseDataByRecursive(&$res, $startTime, $planets, $pid, $need = 'm', $s = '1h', $callback = null)
    {
        $sList = ['1h', '1m', '1s'];
        switch ($s)
        {
            case '1h':
                $n = 24;
                if ($need !== $n) $nextS = '1m';
                else call_user_func($callback, $res);
                break;
            case '1m':
                $n = 1440;
                if ($need !== $n) $nextS = '1s';
                break;
            case '1s':
                $n = 60;
                if ($need !== $n) $nextS = '1s';
                break;
        }
        if ($need !== $n)
        {
            call_user_func($callback, $res);
        }
    }

    /**
     * 获取推荐解锁的功能
     * @param array $data
     */
    public function recommendUnlock(&$data = [])
    {
        if (count($data) < 15) return false;
        $execPrefix = config('astrolog.prefix');
        $astro = Astrolog::getInstance()
            ->setRecode1($this->mainRecord)
            ->setAdvance($this->advance)
            ->setExecPrefix($execPrefix)
            ->setIsAstrolabe(true)
            ->setUserSetting($this->setting)
            ->setVersion(2)
            ->setGetDatas(['natal', 'transits', 'thirdprogressed'])
            ->getAstroDatas();
        // 获取本命盘数据
        $natalData = json_decode(json_encode($astro->getDatas('natal')), true);
        $transitsData = json_decode(json_encode($astro->getDatas('transits')), true);
        $thirdprogressedData = json_decode(json_encode($astro->getDatas('thirdprogressed')), true);


        $activeResult = [];
        $Planetpower = new Planetpower($natalData);
        $Housepower = new Housescore($natalData);
        $planetPowerData = $Planetpower->_initload();
        $housePowerData = $Housepower->_initload();
        /**
         * 计算各宫影响力（现有）
         * 财富=2宫+8宫
         * 事业=6宫+10宫
         * 爱情=5宫+11宫
         * 学识=3宫+9宫
         * 婚姻=7宫*2
         * 单独计算影响力百分比
         */
        $houseImpact = [
            'money' => $housePowerData[1]['active'] + $housePowerData[7]['active'],
            'carrer' => $housePowerData[5]['active'] + $housePowerData[9]['active'],
            'love' => $housePowerData[4]['active'] + $housePowerData[10]['active'],
            'study' => $housePowerData[2]['active'] + $housePowerData[8]['active'],
            'datting' => $housePowerData[6]['active'] * 2,
        ];
        // 计算总活跃值
        $totalActive = array_sum($houseImpact);
        // 计算百分比
        foreach ($houseImpact as $k1 => $v1)
        {
            $houseImpact[$k1] = $v1 / $totalActive;
        }
        /**
         * 计算各星活跃度（现有）
         * 金星
         *  如有日月金水火升落天秤 爱情
         *  如无落天秤，有落金牛 财富
         *  以为皆非 爱情、财富
         * 土星 事业
         * 水星 学识
         * 月亮 婚姻
         */
        $planetImpact = [
            'money' => 0,
            'carrer' => 0,
            'love' => 0,
            'study' => 0,
            'datting' => 0,
        ];
        if ($natalData['planets'][0]['in_sign_id'] === 7
            || $natalData['planets'][1]['in_sign_id'] === 7
            || $natalData['planets'][2]['in_sign_id'] === 7
            || $natalData['planets'][3]['in_sign_id'] === 7
            || $natalData['planets'][4]['in_sign_id'] === 7
            || $natalData['planets'][ASC]['in_sign_id'] === 7)
        {
            $planetImpact['love'] += $planetPowerData[3]['active'];
            $planetImpact['money'] += $planetPowerData[3]['active'] * 0.7;
        } elseif ($natalData['planets'][0]['in_sign_id'] === 2
            || $natalData['planets'][1]['in_sign_id'] === 2
            || $natalData['planets'][2]['in_sign_id'] === 2
            || $natalData['planets'][3]['in_sign_id'] === 2
            || $natalData['planets'][4]['in_sign_id'] === 2
            || $natalData['planets'][ASC]['in_sign_id'] === 2)
        {
            $planetImpact['money'] += $planetPowerData[3]['active'];
            $planetImpact['love'] += $planetPowerData[3]['active'] * 0.7;
        } else
        {
            $planetImpact['money'] += $planetPowerData[3]['active'];
            $planetImpact['love'] += $planetPowerData[3]['active'];
        }
        $planetImpact['carrer'] += $planetPowerData[6]['active'];
        $planetImpact['study'] += $planetPowerData[2]['active'];
        $planetImpact['datting'] += $planetPowerData[1]['active'];
        // 计算总活跃值
        $totalActive = array_sum($planetImpact);
        // 计算百分比
        foreach ($planetImpact as $k2 => $v2)
        {
            $planetImpact[$k2] = $v2 / $totalActive;

            $activeResult[$k2] = ($houseImpact[$k2] + $planetImpact[$k2]) / 2;
        }
        $nowTime = time();
        $nowYear = date("Y", $nowTime);
        $nowMonth = date("m", $nowTime);
        $nowDay = date("d", $nowTime);
        $birthYear = $this->mainRecord['year'];
        $birthMonth = $this->mainRecord['month'];
        $birthDay = $this->mainRecord['day'];
        if ($nowMonth < $birthMonth)
        {
            $age = $nowYear - $birthYear - 1;
        } elseif ($nowMonth == $birthMonth)
        {
            if ($nowDay < $birthDay)
            {
                $age = $nowYear - $birthYear - 1;
            } else
            {
                $age = $nowYear - $birthYear;
            }
        } else
        {
            $age = $nowYear - $birthYear;
        }
        /**
         * 考虑年龄（对相关百分比数做操作）
         * 20岁以下 学业百分比翻倍，25岁以上学业百分比折半，35岁以上不推荐学业
         * 16岁以下恋爱折半，16-30岁恋爱加倍，45岁以上不推荐
         * 16岁以下财富事业折半，30岁以上财富事业加倍
         */
        if ($age < 20)
        {
            $activeResult['study'] *= 2;
        } elseif ($age > 35)
        {
            $activeResult['study'] *= 0;
        } elseif ($age > 25)
        {
            $activeResult['study'] *= 0.5;
        }

        if ($age < 16)
        {
            $activeResult['love'] *= 2;
        } elseif ($age > 45)
        {
            $activeResult['love'] *= 0;
        } elseif ($age >= 16 && $age < 30)
        {
            $activeResult['love'] *= 2;
        }

        if ($age < 16)
        {
            $activeResult['money'] *= 0.5;
            $activeResult['carrer'] *= 0.5;
        } elseif ($age > 30)
        {
            $activeResult['money'] *= 2;
            $activeResult['carrer'] *= 2;
        }

        /**
         * 功能推荐
         * 合盘 词条：如果你近期遇到一些新的缘分，不如来尝试用合盘做一下参考吧
         *   三限月金相位、行运金-日月金木命或者行运日木-金
         *   此时检测 三限金星是否跟土天成刑冲相，如果否，推荐合盘
         * 鉴爱 词条：如果遇到合适的人或不错的缘分，鉴爱功能能帮你看一下你和对方在关系中分别能获得什么
         *   前提条件同合盘
         *   在合盘不优先的情况下选择
         * 幸运之城 词条：不同的城市有不同的能量，如您正在计划一场旅行，可以用占星地图做做参考，看哪些地方更适合您
         *   三限月木相位，行运日水金-木
         *   此时检测 三限月亮是否与39宫星体成相，或三限月过39  ，或行运日金水火木落39
         * 解问题、问答 词条：如果遇到了困惑或者棘手的麻烦事，可以借助占卜工具探寻一下解决的方法，或许能给您一点启发
         *   困难词条：行运火土-日月水金刑冲，行运日水金-火土刑冲
         *   此时检测 三限月亮是否与火土海冥成合刑冲，或三限月亮同时与火土海冥之二成相位，或三限月亮有两个或两个以上刑冲相位
         * 年运 词条：您最近的运势相对低迷，明确未来方向对您会有一定帮助，年运或许是您很好的参考
         *   困难词条：三限月亮刑土冥火海且月亮与金木不成相位
         * 月运 词条：在低迷的运势中，了解未来方向有利于提升您的信心并制定新的计划，月运或可帮您做到这一点
         *   困难词条：三限月亮刑土冥火海且月亮与金木不成相位
         * 报告
         * 合盘报告 词条：人与人之间的相处非常复杂，了解你们之间的关系走向以及互动特点，对您驾驭这段关系定能有所帮助。
         *   三限月金相位、三限月木且月木其一在57宫
         * 婚姻格局报告 词条：婚姻或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。
         *   三限 月亮过7宫的任何相位
         * 财富报告 词条：财富或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。
         *   三限 月亮过2/8宫的任何相位
         * 恋爱报告 词条：恋爱或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。
         *   三限 月亮过5、7宫的任何相位
         * 事业报告 词条：事业或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。
         *   三限，月亮过10宫的任何相位
         * 学业报告 词条：学业或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。
         *   三限，月亮过3/9宫的任何相位（22岁前）
         */
        $recommend = [
            0 => [
                'recommend_type' => 1,
                'name' => '合盘',
                'text' => '如果你近期遇到一些新的缘分，不如来尝试用合盘做一下参考吧。',
                'target' => 'local',
                'link' => 'composite?need_auth=1',
            ],
            1 => [
                'recommend_type' => 2,
                'name' => '鉴爱',
                'text' => '如果遇到合适的人或不错的缘分，鉴爱功能能帮你看一下你和对方在关系中分别能获得什么。',
                'target' => 'local',
                'link' => 'identify_love?need_auth=1',
            ],
            2 => [
                'recommend_type' => 3,
                'name' => '幸运之城',
                'text' => '不同的城市有不同的能量，如您正在计划一场旅行，可以用占星地图做做参考，看哪些地方更适合您。',
                'target' => 'local',
                'link' => 'acg_map?need_auth=1',
            ],
            3 => [
                'recommend_type' => 4,
                'name' => '解问题',
                'text' => '如果遇到了困惑或者棘手的麻烦事，可以借助占卜工具探寻一下解决的方法，或许能给您一点启发。',
                'target' => 'local',
                'link' => 'divination_question?type=2&name1=占星骰子&name2=塔罗占卜&need_auth=0',
            ],
            4 => [
                'recommend_type' => 5,
                'name' => '问答',
                'text' => '如果遇到了困惑或者棘手的麻烦事，可以借助占卜工具探寻一下解决的方法，或许能给您一点启发',
                'target' => 'local',
                'link' => 'question_answer_add?qid=0&qtype=0&need_auth=2',
            ],
            5 => [
                'recommend_type' => 6,
                'name' => '年运',
                'text' => '您最近的运势相对低迷，明确未来方向对您会有一定帮助，年运或许是您很好的参考。',
                'target' => 'local',
                'link' => 'fortune_for_year?time=' . date('Y') . '&need_auth=1',// TODO 年运时间处理，判断是否跳当前年
            ],
            6 => [
                'recommend_type' => 7,
                'name' => '月运',
                'text' => '在低迷的运势中，了解未来方向有利于提升您的信心并制定新的计划，月运或可帮您做到这一点。',
                'target' => 'local',
                'link' => 'fortune_for_month?time=' . date('Y-n') . '&need_auth=1',//  TODO 月运时间处理，判断是否跳当前月
            ],
            7 => [
                'recommend_type' => 8,
                'name' => '合盘恋爱报告',
                'text' => '人与人之间的相处非常复杂，了解你们之间的关系走向以及互动特点，对您驾驭这段关系定能有所帮助。',
                'target' => 'local',
                'link' => 'synastry_report_list?srid=1&need_auth=1',
            ],
            8 => [
                'recommend_type' => 9,
                'name' => '婚姻格局报告',
                'text' => '婚姻或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。',
                'target' => 'local',
                'link' => 'report_details?gid=40&need_auth=1',
            ],
            9 => [
                'recommend_type' => 10,
                'name' => '财富报告',
                'text' => '财富或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。',
                'target' => 'local',
                'link' => 'report_details?gid=41&need_auth=1',
            ],
            10 => [
                'recommend_type' => 11,
                'name' => '恋爱格局报告',
                'text' => '恋爱或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。',
                'target' => 'local',
                'link' => 'report_details?gid=39&need_auth=1',
            ],
            11 => [
                'recommend_type' => 12,
                'name' => '事业格局报告',
                'text' => '事业或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。',
                'target' => 'local',
                'link' => 'report_details?gid=42&need_auth=1',
            ],
            12 => [
                'recommend_type' => 13,
                'name' => '学业格局报告',
                'text' => '学业或许是您非常关心的一个问题，了解它会让你获得更多的幸福感。',
                'target' => 'local',
                'link' => 'report_details?gid=52&need_auth=1',
            ],
        ];
        $recommendTime = $data[14]['time'] + 60;
        /**
         * (
         *    [type] => 1 // 类型：1=>换座,2=>逆行,3=>日食,4=>月食,5=>新月,6=>满月,7=>相位,8=>换宫,
         *    [tag] => 天象 // 运势类型
         *    [title] => 月亮拱天王星 // 运势描述文字
         *    [pid] => // 星体ID（仅换座、逆行、换宫有值）
         *    [pid1] => 1 // 相位中的星体1（仅相位有值）
         *    [pid2] => 7 // 相位中的星体2（仅相位有值）
         *    [phase] => 120 // 相位度数 （仅相位有值）
         *    [in_sign_id] => // 星座ID （仅换座、日食、月食、新月、满月有值）
         *    [in_house_id] => // 宫位ID（仅换宫有值）
         *    [state] => 1  // 1=>起始 2=>精准 3=>结束（仅逆行、相位）
         *    [score] => 0.075 // 感受度（仅天象有值）
         *    [time] => 1666391576 // 事件发生时间
         *    [status] => 2 // 1=>好（大笑） 2=>平（微笑） 3=>坏（哭）
         *    [code] => 110112007 // 词条编码 共计9位数 [0]=>天象、行运、三限 [1]=>1相位、2换宫、3换座、4逆行、5日月食 [2&3]=>行星ID[4&5&6]=>相位度数、星座ID、宫位ID[7&8]=>行星ID、逆行2
         * )
         */
        $recommendList = [];
        // TODO 根据时间流数据判断需要推荐的功能
//        foreach ($data as $k1 => $v1)
//        {
//            if ($v1['state'] === 1)
//            {
//                $typeCode = substr($v1['code'], 0, 2);
//                // 三限月金相位、行运金-日月金木命、行运日木-金
//                if (($typeCode === '31' && $v1['pid1'] === 1 && $v1['pid2'] === 3)
//                    || ($typeCode === '21'
//                        && (($v1['pid1'] === 3 && in_array($v1['pid2'], [0, 1, 3, 5], true))
//                            || ($v1['pid2'] === 3 && in_array($v1['pid1'], [0, 5], true)))))
//                {
//                    // 此时检测 三限金星是否跟土天成刑冲相，如果否，推荐合盘
//
//                }
//            }
//        }

        // 三限月金相位、行运金-日月金木命、行运日木-金
        // 此时检测 三限金星是否跟土天成刑冲相，如果否，推荐合盘
        if (isset($thirdprogressedData['planets'][1]['phase']['1-3'])
            || isset($transitsData[1]['planets'][3]['phase']['3-0'])
            || isset($transitsData[1]['planets'][3]['phase']['3-1'])
            || isset($transitsData[1]['planets'][3]['phase']['3-3'])
            || isset($transitsData[1]['planets'][3]['phase']['3-5'])
            || isset($transitsData[1]['planets'][3]['phase']['3-' . $natalData['houses'][1]['protect_ancient_id']])
            || isset($transitsData[1]['planets'][0]['phase']['0-3'])
            || isset($transitsData[1]['planets'][5]['phase']['5-3']))
        {
            // 前提条件同合盘 在合盘不优先的情况下选择
            if ((isset($thirdprogressedData['planets'][3]['phase']['3-6'])
                    && in_array($thirdprogressedData['planets'][3]['phase']['3-6']['phase_e'], [90, 180], true))
                || (isset($thirdprogressedData['planets'][3]['phase']['3-7'])
                    && in_array($thirdprogressedData['planets'][3]['phase']['3-7']['phase_e'], [90, 180], true)))
            {
                $recommendList[] = $recommend[1];
            } else
            {
                $recommendList[] = $recommend[0];
            }
        }
        // 幸运之城
        // 三限月木相位，行运日水金-木
        // 此时检测 三限月亮是否与39宫星体成相，或三限月过39  ，或行运日金水火木落39
        if (isset($thirdprogressedData['planets'][1]['phase']['1-5'])
            || isset($transitsData[1]['planets'][0]['phase']['0-5'])
            || isset($transitsData[1]['planets'][2]['phase']['2-5'])
            || isset($transitsData[1]['planets'][3]['phase']['3-5']))
        {

            if (in_array($thirdprogressedData['planets'][1]['in_house_id'], [3, 9], true)
                || in_array($transitsData[1]['planets'][0]['in_house_id'], [3, 9], true)
                || in_array($transitsData[1]['planets'][2]['in_house_id'], [3, 9], true)
                || in_array($transitsData[1]['planets'][3]['in_house_id'], [3, 9], true)
                || in_array($transitsData[1]['planets'][4]['in_house_id'], [3, 9], true)
                || in_array($transitsData[1]['planets'][5]['in_house_id'], [3, 9], true))
            {
                $recommendList[] = $recommend[2];
            } else
            {
                if (!empty($thirdprogressedData['planets'][1]['phase']))
                {
                    foreach ($thirdprogressedData['planets'][1]['phase'] as $ph)
                    {
                        if (in_array($thirdprogressedData['planets'][$ph['id']]['in_house_id'], [3, 9], true))
                        {
                            $recommendList[] = $recommend[2];
                            break;
                        }
                    }
                }
            }
        }
        // 解问题、问答
        //	困难词条：行运火土-日月水金刑冲，行运日水金-火土刑冲
        //	此时检测 三限月亮是否与火土海冥成合刑冲，或三限月亮同时与火土海冥之二成相位，或三限月亮有两个或两个以上刑冲相位
        if ((isset($transitsData[1]['planets'][4]['phase']['4-0']) && in_array($transitsData[1]['planets'][4]['phase']['4-0']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][4]['phase']['4-1']) && in_array($transitsData[1]['planets'][4]['phase']['4-1']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][4]['phase']['4-2']) && in_array($transitsData[1]['planets'][4]['phase']['4-2']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][4]['phase']['4-3']) && in_array($transitsData[1]['planets'][4]['phase']['4-3']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][6]['phase']['6-0']) && in_array($transitsData[1]['planets'][6]['phase']['6-0']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][6]['phase']['6-1']) && in_array($transitsData[1]['planets'][6]['phase']['6-1']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][6]['phase']['6-2']) && in_array($transitsData[1]['planets'][6]['phase']['6-2']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][6]['phase']['6-3']) && in_array($transitsData[1]['planets'][6]['phase']['6-3']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][0]['phase']['0-4']) && in_array($transitsData[1]['planets'][0]['phase']['0-4']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][0]['phase']['0-6']) && in_array($transitsData[1]['planets'][0]['phase']['0-6']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][2]['phase']['2-4']) && in_array($transitsData[1]['planets'][2]['phase']['2-4']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][2]['phase']['2-6']) && in_array($transitsData[1]['planets'][2]['phase']['2-6']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][3]['phase']['3-4']) && in_array($transitsData[1]['planets'][3]['phase']['3-4']['phase_e'], [90, 180], true))
            || (isset($transitsData[1]['planets'][3]['phase']['3-6']) && in_array($transitsData[1]['planets'][3]['phase']['3-6']['phase_e'], [90, 180], true))
        )
        {
            $cd1 = false;
            $cd2 = 0;
            $cd3 = 0;
            if (!empty($thirdprogressedData['planets'][1]['phase']))
            {
                foreach ($thirdprogressedData['planets'][1]['phase'] as $ph)
                {
                    if ($ph['id'] < 10)
                    {
                        if (in_array($ph['id'], [4, 6, 8, 9], true))
                        {
                            if (in_array($ph['phase_e'], [0, 90, 180], true))
                            {
                                $cd1 = true;
                                break;
                            }
                            $cd2++;
                        }
                        if (in_array($ph['phase_e'], [90, 180], true))
                        {
                            $cd3++;
                        }
                    }
                }
            }
            if ($cd1 || $cd2 >= 2 || $cd3 >= 2)
            {
                $recommendList[] = $recommend[3];
                $recommendList[] = $recommend[4];
            }
        }
        // 年运：三限月亮刑土冥火海且月亮与金木不成相位
        // 月运：三限月亮刑土冥火海且月亮与金木不成相位
        if (((isset($thirdprogressedData['planets'][1]['phase']['1-4']) && $thirdprogressedData['planets'][1]['phase']['1-4']['phase_e'] === 90)
                || (isset($thirdprogressedData['planets'][1]['phase']['1-6']) && $thirdprogressedData['planets'][1]['phase']['1-6']['phase_e'] === 90)
                || (isset($thirdprogressedData['planets'][1]['phase']['1-8']) && $thirdprogressedData['planets'][1]['phase']['1-8']['phase_e'] === 90)
                || (isset($thirdprogressedData['planets'][1]['phase']['1-9']) && $thirdprogressedData['planets'][1]['phase']['1-9']['phase_e'] === 90))
            && !isset($thirdprogressedData['planets'][1]['phase']['1-3'])
            && !isset($thirdprogressedData['planets'][1]['phase']['1-5']))
        {
            $recommendList[] = $recommend[5];
            $recommendList[] = $recommend[6];
        }
        // 合盘报告：三限月金相位、三限月木且月木其一在57宫
        if (isset($thirdprogressedData['planets'][1]['phase']['1-3'])
            || (isset($thirdprogressedData['planets'][1]['phase']['1-5'])
                && (in_array($thirdprogressedData['planets'][1]['in_house_id'], [5, 7], true)
                    || in_array($thirdprogressedData['planets'][5]['in_house_id'], [5, 7], true))))
        {
            $recommendList[] = $recommend[7];
        }
        // 婚姻格局报告 三限 月亮过7宫的任何相位
        if (!empty($thirdprogressedData['planets'][1]['phase']))
        {
            foreach ($thirdprogressedData['planets'][1]['phase'] as $ph)
            {
                if ($ph['id'] < 10)
                {
                    if ($thirdprogressedData['planets'][1]['in_house_id'] === 7)
                    {
                        $recommendList[] = $recommend[8];
                    }
                    if (in_array($thirdprogressedData['planets'][1]['in_house_id'], [2, 8], true))
                    {
                        $recommendList[] = $recommend[9];
                    }
                    if (in_array($thirdprogressedData['planets'][1]['in_house_id'], [5, 7], true))
                    {
                        $recommendList[] = $recommend[10];
                    }
                    if ($thirdprogressedData['planets'][1]['in_house_id'] === 10)
                    {
                        $recommendList[] = $recommend[11];
                    }
                    if ($age < 22 && in_array($thirdprogressedData['planets'][1]['in_house_id'], [3, 9], true))
                    {
                        $recommendList[] = $recommend[12];
                    }
                    break;
                }
            }
        }
        $recommendCount = count($recommend);
        $recommendListCount = count($recommendList);
        if ($recommendListCount > 1)
        {
            // TODO 功能推荐根据前面的分数，进行取值
            $res = $recommendList[date('d', $recommendTime) % $recommendListCount];
        } elseif ($recommendListCount === 1)
        {
            $res = $recommendList[0];
        } else
        {
            $res = $recommend[date('d', $recommendTime) % $recommendCount];
        }
        // 功能推荐，追加时间
        $res['time'] = $recommendTime;
        $res['start_time'] = $recommendTime;
        $a1 = array_slice($data, 0, 15);
        $a1[] = $res;
        if (count($data) > 15)
        {
            $a2 = array_slice($data, 15);
            $data = array_merge($a1, $a2);
        } else
        {
            $data = $a1;
        }
        return $res;
    }

    /**
     * 推算进行中的行运相位开始或结束时间
     * @param int $p 行星ID
     * @param float $deg 另一个星体的度数
     * @param int $phase 相位
     * @param int $time 未开始推算的时间
     * @param int $type 0=>=推算开始时间,1=>推算结束时间
     * @return false|int
     */
    protected function getTransitsPhaseTime($p, $deg, $phase, $time, $type)
    {
        $n = 365;
        $s = '1d';
        if ($type === 0)
        {
            $caclTime = strtotime('-' . $n . ' day', $time);
        } else
        {
            $caclTime = strtotime('+' . $n . ' day', $time);
        }
        // 相位的容许度范围
        $orbSetting = $this->setting['transits']['asp_orb_all'];
        // 产生该相位的度数范围
        $aspRange[$phase] = $this->getRangeOfPhaseDeg($deg, $phase, $orbSetting[$phase]);
        // 行星度数
        $utdata = Astrolog::getInstance()->getPlanetDegByTimestamp($p, $caclTime, $n, $s, 'l');
        $x = 1;
        if ($type === 0)
        {
            // 由于第一条数据为最早的时间，所以反向
            $utdata = array_reverse($utdata);
            $x = -1;
        }
        foreach ($utdata as $k1 => $v1)
        {
            $cDeg = (float)$v1;
            // 不成相
            if ($this->isInPhaseRange($cDeg, $aspRange) !== $phase)
            {
                return $time + ($k1 + 1) * $x * 86400;
            }
        }
        return $this->getTransitsPhaseTime($p, $deg, $phase, $caclTime, $type);
    }

    /**
     * 计算行运换座的开始时间或结束时间
     * @param int $p 行星ID
     * @param int $sign 落星座ID
     * @param int $time 未开始推算的时间
     * @param int $type 0=>=推算开始时间,1=>推算结束时间
     * @return int
     */
    protected function getTransitsSignTime($p, $sign, $time, $type)
    {
        $n = 365;
        $s = '1d';
        if ($type === 0)
        {
            $caclTime = strtotime('-' . $n . ' day', $time);
        } else
        {
            $caclTime = strtotime('+' . $n . ' day', $time);
        }
        // 行星度数
        $utdata = Astrolog::getInstance()->getPlanetDegByTimestamp($p, $caclTime, $n, $s, 'l');
        if ($type === 0)
        {
            $count = count($utdata);
            $n = 1;
            // 由于第一条数据为最早的时间，所以反向循环
            for ($i = $count - 1; $i >= 0; $i--)
            {
                $cDeg = (float)$utdata[$i];
                $inSign = ceil($cDeg / 30);
                if ($inSign === 0) $inSign = 1;
                // 不成相
                if ($inSign !== $sign)
                {
                    return $time - $n * 86400;
                }
                $n++;
            }
        } else
        {
            foreach ($utdata as $k1 => $v1)
            {
                $cDeg = (float)$v1;
                $inSign = ceil($cDeg / 30);
                if ($inSign === 0) $inSign = 1;
                // 不成相
                if ($inSign !== $sign)
                {
                    return $time + ($k1 + 1) * 86400;
                }
            }
        }
        return $this->getTransitsSignTime($p, $sign, $caclTime, $type);
    }

    /**
     * 计算行运换宫的开始时间或结束时间
     * @param int $p 行星ID
     * @param int $house 落宫位ID
     * @param array $houses 本命宫位数据
     * @param int $time 未开始推算的时间
     * @param int $type 0=>=推算开始时间,1=>推算结束时间
     * @return float|int
     */
    protected function getTransitsHouseTime($p, $house, $houses, $time, $type)
    {
        $n = 365;
        $s = '1d';
        if ($type === 0)
        {
            $caclTime = strtotime('-' . $n . ' day', $time);
        } else
        {
            $caclTime = strtotime('+' . $n . ' day', $time);
        }
        // 行星度数
        $utdata = Astrolog::getInstance()->getPlanetDegByTimestamp($p, $caclTime, $n, $s, 'l');
        if ($type === 0)
        {
            $count = count($utdata);
            $n = 1;
            // 由于第一条数据为最早的时间，所以反向循环
            for ($i = $count - 1; $i >= 0; $i--)
            {
                $cDeg = (float)$utdata[$i];
                $inHouse = Astrolog::getInstance()->inWhichHouse($cDeg, $houses);
                // 不成相
                if ($inHouse !== $house)
                {
                    return $time - $n * 86400;
                }
                $n++;
            }
        } else
        {
            foreach ($utdata as $k1 => $v1)
            {
                $cDeg = (float)$v1;
                $inHouse = Astrolog::getInstance()->inWhichHouse($cDeg, $houses);
                // 不成相
                if ($inHouse !== $house)
                {
                    return $time + ($k1 + 1) * 86400;
                }
            }
        }
        return $this->getTransitsHouseTime($p, $house, $houses, $caclTime, $type);
    }

    /**
     * 计算三限相位的开始时间和结束时间
     * @param int $p1 星体ID1
     * @param int $p2 星体ID2
     * @param int $phase 相位度数
     * @param int $time 0时区时间
     * @param int $type 0=>=推算开始时间,1=>推算结束时间
     * @return int
     */
    protected function getThirdprogressionPhaseTime($p1, $p2, $phase, $time, $type = 0): int
    {
        // 获取当前三限时间所在 天象时间
        $astro = Astrolog::getInstance();
        $x = $type === 0 ? -1 : 1;
        // 往前/后推一天
        $time += 86400 * $x;
        $timeinfo = [
            'year' => (int)(date('Y', $time)),
            'month' => (int)(date('m', $time)),
            'day' => (int)(date('d', $time)),
            'hour' => (int)(date('H', $time)),
            'minute' => (int)(date('i', $time)),
            'timezone' => 0,
            'is_summer' => 0,
        ];
        $astro = $astro->setAdvance($timeinfo)->setGetDatas(['thirdprogressed'])->getAstroDatas();
        $thirdprogressed = json_decode(json_encode($astro->getDatas('thirdprogressed')), true);
        $key = $p1 . '-' . $p2;
        if (!isset($thirdprogressed['planets'][$p1]['phase'][$key]))
        {
            return $time;
        }
        return $this->getThirdprogressionPhaseTime($p1, $p2, $phase, $time, $type);
    }

    /**
     * 计算三限相位的开始时间和结束时间
     * @param int $p1 星体ID1
     * @param int $p2 星体ID2
     * @param int $phase 相位度数
     * @param int $time 0时区时间
     * @return array
     */
    protected function getThirdprogressionPhaseTime2($p1, $p2, $phase, $time): array
    {
        // 获取当前三限时间所在 天象时间
        $astro = Astrolog::getInstance();
        $record = $astro->getRecode1();
        $birth_JD = $record['ut_jd'];

        $time_before_JD = $birth_JD + floor(($time - $record['ut_timestamp']) / 86400 / 27.321661);// 本命后第几天
        $zeroTime = strtotime(jdtogregorian($time_before_JD));// 0时区时间
        $ccc = date('Y-m-d H:i:s', $zeroTime);
        // 获取开始成相时间
        $startTime = (new AspectChange())->where(['pid1' => $p1, 'pid2' => $p2, 'phase' => $phase, 'state' => 1])
            ->whereTime('time', '<', date('Y-m-d H:i:s', $zeroTime + 86399))
            ->order('time desc')->limit(1)->value('time');
        // 获取结束成相时间
        $endTime = (new AspectChange())->where(['pid1' => $p1, 'pid2' => $p2, 'phase' => $phase, 'state' => 3])
            ->whereTime('time', '>', $startTime)
            ->order('time asc')->limit(1)->value('time');
        // 容错处理，开始时间往前推10天
        if (!$startTime)
        {
            $startTime = $zeroTime - 864000;
        }
        // 容错处理，结束时间往后推10天
        if (!$endTime)
        {
            $endTime = $zeroTime + 864000;
        }
        if ($p1 === 3 && $p2 === 8 && $phase === 0)
        {
            $ddd = 111;
        }


        // 成相时间转换为三限时间
        $startTimeJD = ((strtotime($startTime) - $record['ut_timestamp']) / 86400) * 27.321661 + $birth_JD;
        $startDay = jdtogregorian(floor($startTimeJD));
        $startHour = $startTimeJD - floor($startTimeJD);
        $startTimeCacl = floor(strtotime($startDay) + $startHour * 86400);
        $endTimeJD = ((strtotime($endTime) - $record['ut_timestamp']) / 86400) * 27.321661 + $birth_JD;
        $endDay = jdtogregorian(floor($endTimeJD));
        $endHour = $endTimeJD - floor($endTimeJD);
        $endTimeCacl = floor(strtotime($endDay) + $endHour * 86400);

        // 出生时间 1993-4-8 5:00
        // 推运时间 2022-11-10 15:07
        // 出生时间儒略日：2449085.875
        // 推运时间儒略日：2459894.2965278
        // 儒略日差值：2459894.2965278 - 2449085.875 = 10808.429861111
        // 三限转换系数：27.321661
        // 推运时间相当于出生后的天数：10808.429861111 / 27.321661 = 395.60056701286
        // 相差天数：395
        // 变化比率：0.60056701286

        // 天象相位开始时间：1994-05-07 19:56:30
        // 相位开始时间儒略日：2449480.8305556
        // 相位开始时间儒略日差值：2449480.8305556 - 2449085.875 =  394.95555555541
        // 三限儒略日差值：394.95555555541 * 27.321661 = 10790.841798952
        // 三限儒略日：10790.841798952 + 2449085.875 = 2459876.716798952
        // 三限日期为：


        // 天象相位结束时间：1994-05-08 04:37:47
        $ccc1 = date('Y-m-d H:i:s', $zeroTime);
        $ccc2 = date('Y-m-d H:i:s', $startTimeCacl);
        $ccc3 = date('Y-m-d H:i:s', $endTimeCacl);


        $st = $this->thirdTime2UsedTime(strtotime($startTime), $record['ut_timestamp']);
        $en = $this->thirdTime2UsedTime(strtotime($endTime), $record['ut_timestamp']);

        $ccc4 = date('Y-m-d H:i:s', $st);
        $ccc5 = date('Y-m-d H:i:s', $en);

        return ['start' => $startTimeCacl, 'end' => $endTimeCacl];
    }

    /**
     * 计算三限行星换宫的开始时间与结束时间
     * @param $p
     * @param $house
     * @param $time
     * @return array
     */
    protected function getThirdprogressionHouseTime($p, $house, $time): array
    {
        // 获取当前三限时间所在 天象时间
        $astro = Astrolog::getInstance();
        $record = $astro->getRecode1();
        $birth_JD = $record['ut_jd'];
        $longitude = $record['birth_lng'];
        $latitude = $record['birth_lat'];

        $time_before_JD = $birth_JD + floor(($time - $record['ut_timestamp']) / 86400 / 27.321661);// 本命后第几天
        // 转换为出生后那天所对应的时间
        $zeroTime = strtotime(jdtogregorian($time_before_JD));// 0时区时间
//        $zeroTime = strtotime(jdtogregorian(floor($time_before_JD)));// 0时区时间
        /**
         * 这里不知道为什么，步长换成小时就查不到宫位的变化
         * 这里步长使用分钟
         * 获取400分钟数据
         */
        $caclTime = $zeroTime - 720;
//        $ccc = date('Y-m-d H:i:s', $caclTime);
        $utData = Astrolog::getInstance()->getPlanetHouseByTimestamp($caclTime, $p, $longitude, $latitude, 1440, '1d', 'j');
        $startTime = $endTime = null;
        if (!empty($utData))
        {
            foreach ($utData as $k => $v)
            {
                if (isset($utData[$k - 1]))
                {
                    $pre = (int)$utData[$k - 1];
                    $now = (int)$v;
                    if ($pre !== $house && $now === $house)
                    {
                        $startTime = $caclTime + $k * 60;
                    } elseif ($pre === $house && $now !== $house)
                    {
                        $endTime = $caclTime + $k * 60;
                    }
                    if ($startTime !== null && $endTime !== null)
                    {
                        break;
                    }
                }
            }
        }
//        $ddd[] = date('Y-m-d H:i:s', $startTime);
//        $ddd[] = date('Y-m-d H:i:s', $endTime);
        // 开始时间、结束时间转换为三限运势时间
        $startTimeJD = (($startTime - $record['ut_timestamp']) / 86400) * 27.321661 + $birth_JD;
        $startDay = jdtogregorian(floor($startTimeJD));
        $startHour = $startTimeJD - floor($startTimeJD);
        $startTimeCacl = floor(strtotime($startDay) + $startHour * 27.321661 * 86400);
        $endTimeJD = (($endTime - $record['ut_timestamp']) / 86400) * 27.321661 + $birth_JD;
        $endDay = jdtogregorian(floor($endTimeJD));
        $endHour = $endTimeJD - floor($endTimeJD);
        $endTimeCacl = floor(strtotime($endDay) + $endHour * 27.321661 * 86400);

//        $ccc1 = date('Y-m-d H:i:s', $zeroTime);
        $ccc2 = date('Y-m-d H:i:s', $startTimeCacl);
        $ccc3 = date('Y-m-d H:i:s', $endTimeCacl);

        $st = $this->thirdTime2UsedTime($startTime, $record['ut_timestamp']);
        $en = $this->thirdTime2UsedTime($endTime, $record['ut_timestamp']);

        $ccc = [
            date('Y-m-d H:i:s', $startTime),
            date('Y-m-d H:i:s', $endTime),
            date('Y-m-d H:i:s', $zeroTime),
            date('Y-m-d H:i:s', $startTimeCacl),
            date('Y-m-d H:i:s', $endTimeCacl),
            date('Y-m-d H:i:s', $st),
            date('Y-m-d H:i:s', $en),
        ];

        $ccc4 = date('Y-m-d H:i:s', $st);
        $ccc5 = date('Y-m-d H:i:s', $en);

        return ['start' => $st, 'end' => $en];
    }

    /**
     * 三限时间转换为运势时间
     * 三限技法 出生后一天等于之后27.321661天的运势
     * @param $thirdUT
     * @param $birthUT
     * @return null
     */
    protected function thirdTime2UsedTime($thirdUT, $birthUT)
    {
        $res = null;
//        // 出生时间转换为儒略日
//        [$year1, $month1, $day1, $hour1, $minute1] = explode(',', date('Y,m,d,H,i', $birthUT));
//        $birth_JD = gregoriantojd($month1, $day1, $year1) + ($hour1 + ($minute1 / 60)) / 24;// 2449497.25
//        // 三限时间转换为儒略日
//        [$year2, $month2, $day2, $hour2, $minute2] = explode(',', date('Y,m,d,H,i', $thirdUT));
//        $third_JD = gregoriantojd($month2, $day2, $year2) + ($hour2 + ($minute2 / 60)) / 24;// 2449877.1722222
//        // 计算三限时间相当于什么时间的运势（倍数为：27.321661）
//        $day_alive = $third_JD - $birth_JD; // 379.9222222222
//        $days_alive = $day_alive * 27.321661;// 10380.106161922
//        // 整数部分转日期
////        $start_JD = floor($days_alive) + $birth_JD;
//        $start_JD = $days_alive + $birth_JD;// 2459877.3561619
//        $days_alive_decimal = $days_alive - floor($days_alive);
//        $startTimestamp = strtotime(jdtogregorian($start_JD));//
//        $startTimestamp += floor($days_alive_decimal * 27.321661);
//        $aa2 = date('Y-m-d H:i:s', $startTimestamp);
//        // 运势时间-出生时间=比例天数
//        // 比例天数*27.321661+出生天数=推运时间
//
//        $res = $startTimestamp;

//        $birth_JD = $this->recode1['ut_jd'];// 2449497.25
//        $start_JD = $this->advance['ut_jd'];// 2459901.2631944
//        $days_alive = $start_JD - $birth_JD; // 10404.013194445
//        $prog_time_to_add = $days_alive / $coef; // 380.79724341959
//        $time_before_JD = $birth_JD + floor($prog_time_to_add);// 2449877.25
//        $time_change_pro = $prog_time_to_add - floor($prog_time_to_add);// 0.79724341959258
//        $date_before = strtotime(jdtogregorian($time_before_JD)); 2022-11-17 14:19
//        $date_after = strtotime('+1 day', $date_before);

        // 以下的天数为：1970-01-01 00:00:00 往后多少天
        // 出生的0时区时间戳转化为天数
        $birthDay = $birthUT / 86400;// 7220.9513888889
        // 出生后三限时间转换为天数
        $thirdDay = $thirdUT / 86400;// 7661.1484143519
        $dayDIff = $thirdDay - $birthDay + 1;// 440.19702546296
        // 三限运势 相当于出生后多少天
        $thirdStartDay = $dayDIff * 27.321661;// 12021.53084
        // 转换为天数
        $thirdStartDay2 = $thirdStartDay + $birthDay;// 19242.482228889
        // 取整数部分代表那一个月的起始日期
        $integer = floor($thirdStartDay2);// 19242
        // 小数部分为那27.321661天间的进度
        $decimal = $thirdStartDay2 - $integer;// 0.482228889
        // 转换为结果时间
        $res = $thirdStartDay2 * 86400;

        return $res;
    }

    /**
     * 计算相位感受度得分
     * @param array $data
     * @param string $startTime 开始成相时间datetime格式
     * @param string $endTime 结束成相时间datetime格式
     * @param int $max
     * @return float
     */
    protected function getAspectScore($data, $startTime, $endTime, $max = 40)
    {
        $x = [0 => 10, 1 => 10, 2 => 6, 3 => 6, 4 => 6, 5 => 2, 6 => 2, 7 => 1, 8 => 1, 9 => 1, ASC => 10, MC => 7, 'h1r' => 4];
        //	相位系数
        $y = [0 => 1, 60 => 0.7, 90 => 0.8, 120 => 0.8, 180 => 0.9];
        $s = $s1 = $s2 = $s3 = $s4 = 0;
        if (!empty($this->mainRecord))
        {
            $astro = Astrolog::getInstance();
            // 获取精准成相时间
            $time = (new AspectChange())->where(['pid1' => $data['pid1'], 'pid2' => $data['pid2'], 'phase' => $data['phase'], 'state' => 2])
                ->whereTime('time', 'between', [$startTime, $endTime])
                ->order('time asc')->limit(1)->value('time');

            // 获取行运数据，计算与本命星体的相位
            $transitsTime = strtotime($time);
            // 推进时间
            $timeinfo = [
                'year' => (int)(date('Y', $transitsTime)),
                'month' => (int)(date('m', $transitsTime)),
                'day' => (int)(date('d', $transitsTime)),
                'hour' => (int)(date('H', $transitsTime)),
                'minute' => (int)(date('i', $transitsTime)),
                'timezone' => 0,
                'is_summer' => 0,
            ];
            $transitsData = $astro->setAdvance($timeinfo)->setGetDatas(['transits'])
                ->getAstroDatas()->getAstroDatas()->getDatas('transits');
            $transitsData = json_decode(json_encode($transitsData), true);
            if ($data['type'] == 3)
            {
                // 日食
                $phaseId1 = 0;
                $phaseId2 = 1;
            } else
            {
                $phaseId1 = 1;
                $phaseId2 = 0;
            }
            //	容许系数： <0.5=1;<1=0.95;<1.5=0.85; 0.7
            if (!empty($transitsData[1]['planets'][$phaseId1]['phase']))
            {
                $st = 0;
                $ss = [];
                foreach ($transitsData[1]['planets'][$phaseId1]['phase'] as $phase)
                {
                    // 容许系数：<0.5=1;<1=0.95;<1.5=0.85; 0.7
                    if ($phase['phase_orb'] < 0.5)
                    {
                        $z = 1;
                    } elseif ($phase['phase_orb'] < 1)
                    {
                        $z = 0.95;
                    } elseif ($phase['phase_orb'] < 1.5)
                    {
                        $z = 0.85;
                    } else
                    {
                        $z = 0.7;
                    }
                    $t = $y[$phase['phase_e']] * $z;
                    // 本命星体重要性指数*容许系数*相位系数=单相易感度
                    if ($phase['id'] === $transitsData[0]['houses'][1]['protect_ancient_id'])
                    {
                        $st += $x['h1r'] * $t;
                    }
                    if (isset($x[$phase['id']]))
                    {
                        $st += $x[$phase['id']] * $t;
                    }
                    if ($st > 0)
                    {
                        $ss[] = $st;
                    }
                }
                // 各单相易感度相加/2+最高单相易感度/2
                $s1 += array_sum($ss) / 2 + max($ss) / 2;
            }
            if (!empty($transitsData[1]['planets'][$phaseId2]['phase']))
            {
                $st = 0;
                $ss = [];
                foreach ($transitsData[1]['planets'][$phaseId2]['phase'] as $phase)
                {
                    // 容许系数：<0.5=1;<1=0.95;<1.5=0.85; 0.7
                    if ($phase['phase_orb'] < 0.5)
                    {
                        $z = 1;
                    } elseif ($phase['phase_orb'] < 1)
                    {
                        $z = 0.95;
                    } elseif ($phase['phase_orb'] < 1.5)
                    {
                        $z = 0.85;
                    } else
                    {
                        $z = 0.7;
                    }
                    $t = $y[$phase['phase_e']] * $z;
                    // 本命星体重要性指数*容许系数*相位系数=单相易感度
                    if ($phase['id'] === $transitsData[0]['houses'][1]['protect_ancient_id'])
                    {
                        $st += $x['h1r'] * $t;
                    }
                    if (isset($x[$phase['id']]))
                    {
                        $st += $x[$phase['id']] * $t;
                    }
                    if ($st > 0)
                    {
                        $ss[] = $st;
                    }
                }
                // 各单相易感度相加/2+最高单相易感度/2
                $s2 += array_sum($ss) / 2 + max($ss) / 2;
            }

            switch ($transitsData[1]['planets'][$phaseId1]['in_house_id'])
            {
                case 1:
                case 10:
                    $s3 += 4;
                    break;
                case 2:
                case 8:
                case 9:
                    $s3 += 2;
                    break;
                case 3:
                case 6:
                case 12:
                    $s3++;
                    break;
                case 4:
                case 5:
                case 7:
                case 11:
                    $s3 += 3;
                    break;
            }
            switch ($transitsData[1]['planets'][$phaseId2]['in_house_id'])
            {
                case 1:
                case 10:
                    $s3 += 4;
                    break;
                case 2:
                case 8:
                case 9:
                    $s3 += 2;
                    break;
                case 3:
                case 6:
                case 12:
                    $s3++;
                    break;
                case 4:
                case 5:
                case 7:
                case 11:
                    $s3 += 3;
                    break;
            }

            // 参与相位的星体为命主星 古典
            if ($phaseId1 === $transitsData[0]['houses'][1]['protect_ancient_id'])
            {
                $s4 += 7;
            }
            if ($phaseId2 === $transitsData[0]['houses'][1]['protect_ancient_id'])
            {
                $s4 += 7;
            }
        }

        $s += $s1 + $s2 + $s3 + $s4;
        $s /= $max;
        if ($s > 0.99)
        {
            $s = 0.99;
        } elseif ($s < 0.05)
        {
            $s = 0.05;
        }

        return $s;
    }

    /**
     * 计算天象逆感受度得分
     * @param array $data 逆行数据
     * @param int $startTime 逆行开始时间 时间戳
     * @param int $endTime 逆行结束时间 时间戳
     * @param int $max 最大值
     * @return float|int
     */
    protected function getRetroScore($data, $startTime, $endTime, $max = 20)
    {
        $x = [0 => 10, 1 => 10, 2 => 6, 3 => 6, 4 => 6, 5 => 2, 6 => 2, 7 => 1, 8 => 1, 9 => 1, ASC => 10, MC => 7, 'h1r' => 4];
        //	相位系数
        $y = [0 => 1, 60 => 0.7, 90 => 0.8, 120 => 0.8, 180 => 0.9];
        $s = $s1 = $s2 = $s3 = $s4 = 0;
        $st1 = 0;
        $phaseIds = [];
        if (!empty($this->mainRecord))
        {
            $astro = Astrolog::getInstance();
            /**
             * 根据逆行起点和终点  获取行运盘数据
             */
            // 推进时间
            $timeinfo1 = [
                'year' => (int)(date('Y', $startTime)),
                'month' => (int)(date('m', $startTime)),
                'day' => (int)(date('d', $startTime)),
                'hour' => (int)(date('H', $startTime)),
                'minute' => (int)(date('i', $startTime)),
                'timezone' => 0,
                'is_summer' => 0,
            ];
            /**
             * 逆行起点成相情况
             * 逆行星体ID=$data['pid']
             */
            $startTransitsData = $astro->setAdvance($timeinfo1)->setGetDatas(['transits'])
                ->getAstroDatas()->getAstroDatas()->getDatas('transits');
            $startTransitsData = json_decode(json_encode($startTransitsData), true);
            // 推进时间
            $timeinfo2 = [
                'year' => (int)(date('Y', $endTime)),
                'month' => (int)(date('m', $endTime)),
                'day' => (int)(date('d', $endTime)),
                'hour' => (int)(date('H', $endTime)),
                'minute' => (int)(date('i', $endTime)),
                'timezone' => 0,
                'is_summer' => 0,
            ];
            /**
             * 逆行终点成相情况
             * 逆行星体ID=$data['pid']
             */
            $endTransitsData = $astro->setAdvance($timeinfo2)->setGetDatas(['transits'])
                ->getAstroDatas()->getAstroDatas()->getDatas('transits');
            $endTransitsData = json_decode(json_encode($endTransitsData), true);
            // 成相
            if (!empty($startTransitsData[1]['planets'][$data['pid']]['phase']))
            {
                foreach ($startTransitsData[1]['planets'][$data['pid']]['phase'] as $k3 => $v3)
                {
                    // 容许系数：<0.5=1;<1=0.95;<1.5=0.85; 0.7
                    if ($v3['phase_orb'] < 0.5)
                    {
                        $z = 1;
                    } elseif ($v3['phase_orb'] < 1)
                    {
                        $z = 0.95;
                    } elseif ($v3['phase_orb'] < 1.5)
                    {
                        $z = 0.85;
                    } else
                    {
                        $z = 0.7;
                    }
                    $t = $y[$v3['phase_e']] * $z * 2;
                    // 本命星体重要性指数*容许系数*相位系数*2=易感度
                    if ($v3['id'] === $startTransitsData[0]['houses'][1]['protect_ancient_id'])
                    {
                        $st1 += $x['h1r'] * $t;
                        $phaseIds[] = $v3['id'];
                    }
                    if (isset($x[$v3['id']]))
                    {
                        $st1 += $x[$v3['id']] * $t;
                        $phaseIds[] = $v3['id'];
                    }
                }
            }
            // 成相
            if (!empty($endTransitsData[1]['planets'][$data['pid']]['phase']))
            {
                foreach ($endTransitsData[1]['planets'][$data['pid']]['phase'] as $k4 => $v4)
                {
                    // 容许系数：<0.5=1;<1=0.95;<1.5=0.85; 0.7
                    if ($v4['phase_orb'] < 0.5)
                    {
                        $z = 1;
                    } elseif ($v4['phase_orb'] < 1)
                    {
                        $z = 0.95;
                    } elseif ($v4['phase_orb'] < 1.5)
                    {
                        $z = 0.85;
                    } else
                    {
                        $z = 0.7;
                    }
                    $t = $y[$v4['phase_e']] * $z * 2;
                    // 本命星体重要性指数*容许系数*相位系数*2=易感度
                    if ($v4['id'] === $endTransitsData[0]['houses'][1]['protect_ancient_id'])
                    {
                        $st1 += $x['h1r'] * $t;
                        $phaseIds[] = $v4['id'];
                    }
                    if (isset($x[$v4['id']]))
                    {
                        $st1 += $x[$v4['id']] * $t;
                        $phaseIds[] = $v4['id'];
                    }
                }
            }
            $s1 += $st1;
            //	判断本命是否有星体不跟起点终点成相位，但在成相位的区间上（与起点终点之间的任一点成相）
            //		本命星体重要性指数*容许系数*相位系数*=易感度
            // 与起点和终点成相位的星体去重
            $phaseIds = array_unique($phaseIds);
            $pids = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ASC, MC];
            // 未与起点和终点成相的星体
            $needPids = array_diff($pids, $phaseIds);
            if (!empty($needPids))
            {
                // 逆行星体起点度数
                $startDeg = $startTransitsData[1]['planets'][$data['pid']]['deg'];
                // 逆行星体终点度数
                $endDeg = $endTransitsData[1]['planets'][$data['pid']]['deg'];
                // 计算起点到终点的区间
                $sections = [];
                // 由于是逆行  所以终点一定比起点度数要小
                if ($endDeg > $startDeg)
                {
                    $sections[] = [0, $startDeg];
                    $sections[] = [$endDeg, 360];
                } else
                {
                    $sections[] = [$endDeg, $startDeg];
                }
                // 行运相位容许度
                $orbSetting = $this->setting['transits']['asp_orb_all'];
                $asps = [0, 60, 90, 120, 180];
                $st2 = 0;
                foreach ($needPids as $k5 => $v5)
                {
                    // 本命星体度数
                    $v5Deg = $startTransitsData[0]['planets'][$v5]['deg'];
                    // 遍历需要检测的相位
                    foreach ($asps as $a)
                    {
                        $l = $a + $v5Deg + $orbSetting[$a];
                        $r = $a + $v5Deg - $orbSetting[$a];
                        if ($l >= 360)
                        {
                            $l -= 360;
                        }
                        if ($r < 0)
                        {
                            $r += 360;
                        }
                        $isPhase = false;
                        foreach ($sections as $sec)
                        {
                            if (($l >= $sec[0] && $l <= $sec[1]) || ($r >= $sec[0] && $r <= $sec[1]))
                            {
                                $isPhase = true;
                                break;
                            }
                        }
                        if ($isPhase === true)
                        {
                            // 本命星体重要性指数*容许系数*相位系数=易感度
                            $stt = $x[$v5] * 1 * $y[$a];
                            if ($stt > $st2)
                            {
                                $st2 = $stt;
                            }
                        }
                    }
                }
                $s2 += $st2;
            }

            // 逆行的星体为命主星 古典或现代
            if ($data['pid'] === $endTransitsData[0]['houses'][1]['protect_ancient_id'])
            {
                $s3 += 7;
            }

            //	判断逆行行经宫位
            //		角
            //			1-4，,10-4，,7-3，,4-3
            //		续
            //			2-2，,8-2，,5-3，11-3
            //		果
            //			3-1，,6-1，,9-2，,12-1
            $startHouseId = $startTransitsData[1]['planets'][$data['pid']]['in_house_id'];
            $endHouseId = $endTransitsData[1]['planets'][$data['pid']]['in_house_id'];
            $passHouses = array_unique([$startHouseId, $endHouseId]);
            if ($passHouses > 1)
            {
                for ($i = $startHouseId; $i === $endHouseId; $i--)
                {
                    $i = $i < 1 ? 12 : $i;
                    if (!in_array($i, $passHouses, true))
                    {
                        $passHouses[] = $i;
                    }
                }
            }
            foreach ($passHouses as $ph)
            {
                switch ($ph)
                {
                    case 1:
                    case 10:
                        $s4 += 4;
                        break;
                    case 2:
                    case 8:
                    case 9:
                        $s4 += 2;
                        break;
                    case 3:
                    case 6:
                    case 12:
                        $s4++;
                        break;
                    case 4:
                    case 5:
                    case 7:
                    case 11:
                        $s4 += 3;
                        break;
                }
            }
        }

        $s += $s1 + $s2 + $s3 + $s4;
        $s /= $max;
        if ($s > 0.99)
        {
            $s = 0.99;
        } elseif ($s < 0.05)
        {
            $s = 0.05;
        }
        return $s;
    }
}
